mirror of https://gitee.com/stylefeng/roses
【8.3.4】【rule】更新一个code生成器的工具类
parent
808f7ad458
commit
3956efe691
|
@ -0,0 +1,44 @@
|
|||
package cn.stylefeng.roses.kernel.rule.code;
|
||||
|
||||
|
||||
/**
|
||||
* 二维码的唯一编码生成的规则
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @since 2025/4/20 18:49
|
||||
*/
|
||||
public class CodeGenerateUtil {
|
||||
|
||||
/**
|
||||
* 生成不同规则的二维码编码字符串
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @since 2025/4/20 18:50
|
||||
*/
|
||||
public static String generateQrCode(CodeStrategy codeStrategy, Integer codeLength) {
|
||||
|
||||
// 初始化生成器(需确保workerId和datacenterId集群唯一)
|
||||
UniqueTraceCodeGenerator generator = UniqueTraceCodeGenerator.getInstance();
|
||||
|
||||
// 生成固定15位混合编码
|
||||
return generator.generateCode(codeStrategy, codeLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用示例
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @since 2025/4/20 18:49
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
System.out.println("混合编码: " + CodeGenerateUtil.generateQrCode(CodeStrategy.MIXED, 15));
|
||||
System.out.println("大写编码: " + CodeGenerateUtil.generateQrCode(CodeStrategy.UPPERCASE, 15));
|
||||
System.out.println("小写编码: " + CodeGenerateUtil.generateQrCode(CodeStrategy.LOWERCASE, 15));
|
||||
System.out.println("数字编码: " + CodeGenerateUtil.generateQrCode(CodeStrategy.DIGITS, 15));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package cn.stylefeng.roses.kernel.rule.code;
|
||||
|
||||
/**
|
||||
* 编码策略定义
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @since 2025/4/20 18:40
|
||||
*/
|
||||
public enum CodeStrategy {
|
||||
|
||||
/**
|
||||
* 混合编码
|
||||
*/
|
||||
MIXED(62, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
|
||||
|
||||
/**
|
||||
* 大写字母
|
||||
*/
|
||||
UPPERCASE(26, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
|
||||
|
||||
/**
|
||||
* 纯小写字母
|
||||
*/
|
||||
LOWERCASE(26, "abcdefghijklmnopqrstuvwxyz"),
|
||||
|
||||
/**
|
||||
* 数字
|
||||
*/
|
||||
DIGITS(10, "0123456789");
|
||||
|
||||
final int base;
|
||||
|
||||
final String charset;
|
||||
|
||||
CodeStrategy(int base, String charset) {
|
||||
this.base = base;
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成规则的枚举
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @since 2025/4/20 19:42
|
||||
*/
|
||||
public static CodeStrategy getByCode(Integer codeStrategyType) {
|
||||
if (codeStrategyType.equals(1)) {
|
||||
return DIGITS;
|
||||
} else if (codeStrategyType.equals(2)) {
|
||||
return UPPERCASE;
|
||||
} else if (codeStrategyType.equals(3)) {
|
||||
return LOWERCASE;
|
||||
} else if (codeStrategyType.equals(4)) {
|
||||
return MIXED;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
package cn.stylefeng.roses.kernel.rule.code;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 绝对唯一的溯源编码生成器
|
||||
* 基于 UUID 和哈希算法实现,支持四种编码策略
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @since 2025/4/20 18:42
|
||||
*/
|
||||
public class UniqueTraceCodeGenerator {
|
||||
|
||||
/**
|
||||
* 单例控制
|
||||
*/
|
||||
private static volatile UniqueTraceCodeGenerator instance;
|
||||
|
||||
private UniqueTraceCodeGenerator() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 单例实例的创建
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @since 2025/4/20 18:41
|
||||
*/
|
||||
public static UniqueTraceCodeGenerator getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (UniqueTraceCodeGenerator.class) {
|
||||
if (instance == null) {
|
||||
instance = new UniqueTraceCodeGenerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一编码
|
||||
*
|
||||
* @param strategy 编码策略
|
||||
* @param length 固定长度(不足补首字符)
|
||||
* @return 生成的编码
|
||||
* @author fengshuonan
|
||||
* @since 2025/4/20 18:42
|
||||
*/
|
||||
public String generateCode(CodeStrategy strategy, int length) {
|
||||
// 生成 UUID
|
||||
String uuid = UUID.randomUUID().toString().replace("-", "");
|
||||
|
||||
// 对 UUID 进行哈希处理
|
||||
String hashedUuid = hash(uuid);
|
||||
|
||||
// 转换为指定编码策略
|
||||
return convert(hashedUuid, strategy, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 哈希算法(SHA-256)
|
||||
*
|
||||
* @param input 输入字符串
|
||||
* @return 哈希后的字符串
|
||||
* @author fengshuonan
|
||||
* @since 2025/4/20 18:42
|
||||
*/
|
||||
private String hash(String input) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] hashBytes = digest.digest(input.getBytes());
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
for (byte b : hashBytes) {
|
||||
String hex = Integer.toHexString(0xff & b);
|
||||
if (hex.length() == 1) {
|
||||
hexString.append('0');
|
||||
}
|
||||
hexString.append(hex);
|
||||
}
|
||||
return hexString.toString();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("哈希算法异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 进制转换核心算法
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @since 2025/4/20 18:42
|
||||
*/
|
||||
private String convert(String input, CodeStrategy strategy, int fixLength) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int base = strategy.base;
|
||||
String charset = strategy.charset;
|
||||
|
||||
// 将输入的哈希值(16进制字符串)转换为指定编码策略
|
||||
for (int i = 0; i < input.length(); i += 2) {
|
||||
// 每次取两个字符(一个字节)
|
||||
String hex = input.substring(i, i + 2);
|
||||
int byteValue = Integer.parseInt(hex, 16);
|
||||
|
||||
// 将字节值转换为指定编码字符
|
||||
sb.append(charset.charAt(byteValue % base));
|
||||
}
|
||||
|
||||
// 如果长度不足,补足到固定长度
|
||||
while (sb.length() < fixLength) {
|
||||
sb.append(charset.charAt(0));
|
||||
}
|
||||
|
||||
// 如果长度超过固定长度,截取前 fixLength 个字符
|
||||
if (sb.length() > fixLength) {
|
||||
sb.setLength(fixLength);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue