为了保证全工程生成的随机字符串不重复,查询了相关文档,也看到了一些优秀的实现方式,但都无法满足自己的要求。因此考虑到项目的需要,码了一个工具类。记录于此,共需要的小伙伴参考。
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://url.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 = {
'.', '~', '*', '$', '#'
};
/**----------------------其他实现方式------------------------*/
/**
* 转换方法
*/
private static String transRadix(Long convertNumber) {
StringBuilder sb = new StringBuilder();
while (convertNumber != 0) {
sb.append(CHS[(int) (convertNumber % CHS.length)]);
convertNumber = convertNumber / CHS.length;
}
return sb.reverse().toString();
}
/**
* 设置字符数组
* 可以添加任意不重复字符,提高能转换的进制的上限
*/
private final static char[] CHS = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z',
'a', 'b', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'm',
'n', 'q', 'r', 't', 'y'
};
}
以上,实现方式不仅限于此,欢迎童鞋们一起讨论,也希望可以帮助有需要的童鞋。