唯一码生成工具类

/**
 * 生成码
 */
@Component
@Slf4j
public class GenerateCodeUtils {
    /**
     * 默认重试次数
     */
    public static final int DEFAULT_RETRY_NUM     = 10;
    /**
     * 默认重试时间间隔
     */
    public static final int DEFAULT_SLEEP_TIME    = 1;
    /**
     * 默认自增最大数
     */
    public static final int DEFAULT_MAX_NUM       = 999;
    /**
     * 默认随机数因子
     */
    public static final int DEFAULT_RANDOM_FACTOR = 5;
    /**
     * 默认自增数
     */
    public static final int DEFAULT_DELTA         = 1;
    /**
     * 默认随机数
     */
    public static final int DEFAULT_RANDOM_NUM    = 100;

    private static String        monthDay;
    //自增开始数
    private static AtomicInteger startNum = new AtomicInteger(0);
    //重试次数
    final          int           retryNum;
    //重试时间间隔
    final          int           sleepTime;
    //自增最大数
    final          int           maxNum;
    //随机数因子
    final          int           randomFactor;
    //随机数
    final          int           randomNum;
    //自增数
    final          int           delta;

    public GenerateCodeUtils() {
        this.retryNum = DEFAULT_RETRY_NUM;
        this.sleepTime = DEFAULT_SLEEP_TIME;
        this.maxNum = DEFAULT_MAX_NUM;
        this.randomFactor = DEFAULT_RANDOM_FACTOR;
        this.randomNum = DEFAULT_RANDOM_NUM;
        this.delta = DEFAULT_DELTA;
    }

    /**
     * @param retryNum     重试次数
     * @param sleepTime    重试时间间隔
     * @param maxNum       自增最大数
     * @param randomFactor 随机数因子
     * @param randomNum    随机数
     * @param delta        自增数
     */
    public GenerateCodeUtils(int retryNum, int sleepTime, int maxNum, int randomFactor, int randomNum, int delta) {
        if (retryNum < 0) {
            throw new IllegalArgumentException("Illegal initial retryNum: " +
                    retryNum);
        }
        if (sleepTime < 0) {
            throw new IllegalArgumentException("Illegal initial sleepTime: " +
                    sleepTime);
        }
        if (maxNum <= 0) {
            throw new IllegalArgumentException("Illegal initial maxNum: " +
                    maxNum);
        }

        if (randomNum <= 0) {
            throw new IllegalArgumentException("Illegal initial randomNum: " +
                    randomNum);
        }

        if (delta <= 0) {
            throw new IllegalArgumentException("Illegal initial delta: " +
                    delta);
        }
        this.retryNum = retryNum;
        this.sleepTime = sleepTime;
        this.maxNum = maxNum;
        this.randomFactor = randomFactor;
        this.randomNum = randomNum;
        this.delta = delta;
    }

    public String generateCode(Function<String, Integer> function) {
        LogUtil.info(log, "生成码:{}", Thread.currentThread().getName());
        monthDay = getMonthDay();
        // 设置返回值条件
        String code = getCode(function);
        if (StringUtils.isEmpty(code)) {
            Predicate<String> predicate = Predicates.equalTo(null);
            code = RetryUtils.guavaRetryExecute(retryNum, sleepTime, TimeUnit.SECONDS, Exception.class, () -> {
                LogUtil.info(log, "开始执行可重试方法");
                String resCode = getCode(function);
                if (!StringUtils.isEmpty(resCode)) {
                    LogUtil.info(log, "重试成功");
                    return resCode;
                }
                LogUtil.info(log, "重试失败");
                // 执行需重试业务逻辑
                return null; // 返回值与"null"不相等,不进行重试
            }, predicate, log);
        }
        if (StringUtils.isEmpty(code)) {
            throw new BizException(CodeMsg.CODE_GENERATE_FAIL);
        }
        return code;
    }

    public String getCode(Function<String, Integer> function) {
        //随机字符集
        String randomStr = RandomStringUtils.getRandom(randomFactor);
        //自增数,进程内(sychronize锁)分钟级自增0-999,初始数使用 100以内随机。时间超过1分钟的重新初始化。
        synchronized (this) {
            String newMonthDay = getMonthDay();
            if (startNum.get() >= maxNum) {
                startNum.set(ThreadLocalRandom.current().nextInt(randomNum));
            }

            if (!monthDay.equals(newMonthDay)) {
                monthDay = newMonthDay;
            }
            String startNumStr = String.format("%03d", startNum.addAndGet(delta));
            StringJoiner stringJoiner = new StringJoiner("");
            String code = stringJoiner.add(monthDay).add(randomStr).add(startNumStr).toString();
            Integer count = function.apply(code);
            if (count > 0) {
                return null;
            }
            return code;
        }
    }

    public String getMonthDay() {
        LocalDate date = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMdd");
        return date.format(formatter);
    }

}
import java.util.concurrent.ThreadLocalRandom;

/**
 * 随机字符集: 小写字母 a-z(去除i/l等易与数字混淆)、0-9
 */
public class RandomStringUtils {
    private static final char[] CHARS = new char[] {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N',
        'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};

    /**
     * 获取随机字符串
     *
     * @param size 长度
     * @return String 随机字符串
     */
    public static String getRandom(int size) {
        StringBuilder s = new StringBuilder();
        for (int i = 0; i < size; i++) {
            s.append(CHARS[ThreadLocalRandom.current().nextInt(CHARS.length)]);
        }
        return s.toString();
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没事搞点事做serendipity

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值