From 3956efe691d46673c8d2dbf95e02ff81e4163684 Mon Sep 17 00:00:00 2001 From: stylefeng Date: Sun, 4 May 2025 22:28:01 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=908.3.4=E3=80=91=E3=80=90rule=E3=80=91?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=B8=80=E4=B8=AAcode=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=99=A8=E7=9A=84=E5=B7=A5=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kernel/rule/code/CodeGenerateUtil.java | 44 +++++++ .../roses/kernel/rule/code/CodeStrategy.java | 59 +++++++++ .../rule/code/UniqueTraceCodeGenerator.java | 121 ++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/code/CodeGenerateUtil.java create mode 100644 kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/code/CodeStrategy.java create mode 100644 kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/code/UniqueTraceCodeGenerator.java diff --git a/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/code/CodeGenerateUtil.java b/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/code/CodeGenerateUtil.java new file mode 100644 index 000000000..b0c0ffe1d --- /dev/null +++ b/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/code/CodeGenerateUtil.java @@ -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)); + } + + } + +} diff --git a/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/code/CodeStrategy.java b/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/code/CodeStrategy.java new file mode 100644 index 000000000..8f53903a7 --- /dev/null +++ b/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/code/CodeStrategy.java @@ -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; + } + +} \ No newline at end of file diff --git a/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/code/UniqueTraceCodeGenerator.java b/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/code/UniqueTraceCodeGenerator.java new file mode 100644 index 000000000..923bf9dee --- /dev/null +++ b/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/code/UniqueTraceCodeGenerator.java @@ -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(); + } + +} \ No newline at end of file