基於Redis存儲利用進位制思想生成不重複的隨機字符串

隨機字符串

背景

爲了保證全工程生成的隨機字符串不重複,查詢了相關文檔,也看到了一些優秀的實現方式,但都無法滿足自己的要求。因此考慮到項目的需要,碼了一個工具類。記錄於此,共需要的小夥伴參考。

代碼片

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Random;

/**
 * @author: hilbert
 * @description: 利用十進制數與64進制的轉換算法,生成6位字符串,自增序列通過redis控制
 * @date: Created in 16:43 2019/8/7
 * @modified By:
 */
@Slf4j
@Component
public class RandomStringUtil {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private static StringRedisTemplate redisTemplate;

    @PostConstruct
    public void init() {
        redisTemplate = stringRedisTemplate;
    }

    /**
     * 自增值緩存key
     */
    private final static String INCREMENT_KEY = "incr:key";

    /**
     * @param args
     */
    public static void main(String[] args) {
        String convert = convert(68719476735L);
        System.out.println("https://s.hzg6.cn/" + convert);
    }

    /**
     * 生成六位字符串
     */
    public static String randomStrSix() {
        String incr = redisTemplate.opsForValue().get(INCREMENT_KEY);
        Long increment = 0L;
        if (StringUtils.isNotBlank(incr)) {
            increment = redisTemplate.opsForValue().increment(INCREMENT_KEY, 1);
        } else {
            redisTemplate.opsForValue().set(INCREMENT_KEY, increment.toString());
        }
        log.info("已生成的自增值={}", increment);
        return convert(increment);
    }

    /**
     * 把10進制的數字轉換成64進制
     * 目前最大支持:68719476735
     */
    private static String convert(Long convertNumber) {
        if (convertNumber == null) {
            throw new IllegalArgumentException("待轉換參數有誤");
        }
        long tempNum = convertNumber;
        char[] buf = new char[DIGITS.length];
        int charPos = DIGITS.length;
        long mask = DIGITS.length - 1;
        do {
            buf[--charPos] = DIGITS[(int) (convertNumber & mask)];
            convertNumber >>>= 6;
        } while (convertNumber != 0);
        String randomStr = new String(buf, charPos, (64 - charPos));
        if (randomStr.length() > 6) {
            throw new IllegalArgumentException(String.format("帶轉換參數%s已超過可處理的數字範圍。", tempNum));
        }
        randomStr = randomStr() + randomStr;
        return randomStr.substring(randomStr.length() - 6);
    }

    /**
     * 隨機補位串
     */
    private static String randomStr() {
        Random random = new Random();
        int length = ADDITIONAL_DIGITS.length;
        StringBuilder randomStr = new StringBuilder();
        for (int i = 0; i < length; i++) {
            randomStr.append(ADDITIONAL_DIGITS[random.nextInt(length)]);
        }
        return randomStr.toString();
    }

    /**
     * 加密串組
     * 隨機排列,保障串的隨機性
     */
    private final static char[] DIGITS = {
            'i', 'B', 'l', '8', 'Y', 'n',
            '0', 'K', 'y', 'W', 'p', 'F',
            'A', 'h', 'J', 'x', 'E', '9',
            '6', 'd', 'U', 'g', 'P', 'j',
            'c', 'Q', '2', 'O', 'b', 'N',
            'a', 'k', '5', 'R', 'e', 'M',
            'o', 'C', 'q', '4', 'S', 't',
            'u', 'T', 'v', 'D', '3', 'z',
            'G', 'w', 'I', 'r', 'L', '1',
            's', 'H', 'f', '-', 'X', '7',
            'm', 'Z', '_', 'V'
    };

    /**
     * 用於生成補位隨機串
     */
    private final static char[] ADDITIONAL_DIGITS = {
            '.', '~', '*', '$', '#'
    };
}

總結

以上,實現方式不僅限於此,歡迎童鞋們一起討論,也希望可以幫助有需要的童鞋。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章