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