yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/BizNoUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package cn.iocoder.yudao.framework.common.util.number;
import java.util.concurrent.ThreadLocalRandom;
/**
 * ä¸šåŠ¡ç¼–ç ï¼ˆå•æ®å· / ä¸»æ•°æ®ç¼–码)生成的公共约定。
 *
 * <p>需求:系统中所有自动生成的业务编码统一为「16 ä½çº¯æ•°å­—」,且**随机生成、不使用自增/顺序**,
 * åŒæ—¶ä¿è¯å…¨ç³»ç»Ÿå”¯ä¸€ï¼ˆä»»æ„ä¸¤æ¡ç¼–码都不重复)。
 *
 * <p>实现约定:
 * <ul>
 *     <li>编码 = éšæœº 16 ä½æ•°å­—(范围 0 ~ 10^16-1,左侧补 '0');</li>
 *     <li>唯一性由 Redis é›†åˆ {@link #USED_SET_KEY} æŸ¥é‡ä¿è¯ï¼šéšæœºç”ŸæˆåŽå†™å…¥é›†åˆï¼Œ
 *         å†™æˆåŠŸï¼ˆè¿”å›ž 1)说明没用过才采用,否则重试;</li>
 *     <li>各生成点:见 {@link #randomCode()} ä¸Ž {@link #MAX_RETRY}。</li>
 * </ul>
 *
 * <p>注意:Redis é›†åˆä¸¢å¤±åŽï¼ŒåŽ†å²ç¼–ç å¯èƒ½è¢«é‡æ–°éšæœºå‘½ä¸­ï¼›åº”ç”¨å¯åŠ¨æ—¶ä¼šå°†åº“å†…å·²æœ‰ç¼–ç 
 * é‡æ–°è½½å…¥é›†åˆï¼ˆè§ yudao-server çš„启动兜底)。
 */
public class BizNoUtils {
    /**
     * å·²ä½¿ç”¨ä¸šåŠ¡ç¼–ç çš„ Redis é›†åˆ KEY,用于随机编码查重,保证全系统唯一。
     */
    public static final String USED_SET_KEY = "biz:code:used";
    /**
     * ä¸šåŠ¡ç¼–ç çš„æ€»é•¿åº¦ï¼š16 ä½
     */
    public static final int CODE_LENGTH = 16;
    /**
     * éšæœºç¼–码的空间上限(不含):10^16
     */
    private static final long CODE_SPACE = 10_000_000_000_000_000L;
    /**
     * ç”Ÿæˆéšæœºç¼–码时的最大重试次数(命中已用编码时重试)
     */
    public static final int MAX_RETRY = 10;
    /**
     * ç”Ÿæˆä¸€ä¸ªéšæœº 16 ä½çº¯æ•°å­—编码(左侧补 '0'),**不做查重**。
     *
     * <p>调用方需自行用 {@link #USED_SET_KEY} æŸ¥é‡ï¼Œå‘½ä¸­åˆ™é‡è¯•。
     *
     * @return éšæœº 16 ä½çº¯æ•°å­—编码
     */
    public static String randomCode() {
        return String.format("%0" + CODE_LENGTH + "d", ThreadLocalRandom.current().nextLong(CODE_SPACE));
    }
}