通过redis的increment方法来记录流水编号,java中经常会用到固定字符+日期+几位流水号的编号格式,这里记录一下生成编号的通用类。我重写了两个方法,一个带日期格式的,一个没有日期格式的;

实现代码如下:

public class NumberUtils {
    private NumberUtils() {}

    /**
     * 编号自动生成
     *
     * @param redisTemplate redis模板
     * @param code          前缀 首字母大写
     * @param nums          几位数字
     * @return 编号
     */
    @NotNull
    public static String generateSerialNum(RedisTemplate<String,Integer> redisTemplate,
                                           String code, Integer nums) {
        // nums位数字,不够的前面补0
        val format = String.format("%%0%dd", nums);
        // 返回拼接好的编号
        return code +
                // redisKey组成:前缀,确保每天都是新的key,编号从0001开始
                String.format(format, getIncrement(redisTemplate, code));
    }

    /**
     * 编号自动生成
     *
     * @param redisTemplate redis模板
     * @param code          前缀 首字母大写
     * @param dateFormat    日期格式
     * @param nums          几位数字
     * @return 编号
     */
    @NotNull
    public static String generateSerialNum(RedisTemplate<String,Integer> redisTemplate,
                                           String code, String dateFormat, Integer nums) {
        // nums位数字,不够的前面补0
        val format = String.format("%%0%dd", nums);

        // 返回拼接好的编号
        return code + DateUtils.formatDate(new Date(), dateFormat)
                // redisKey组成:前缀+格式化后的具体日期,确保每天都是新的key,编号从0001开始
                + String.format(format, getIncrement(redisTemplate, code + DateUtils.formatDate(new Date(), dateFormat)));
    }

    private static Integer getIncrement(@NotNull RedisTemplate<String,Integer> redisTemplate, String redisKey) {
        return Optional.ofNullable(redisTemplate.opsForValue().get(redisKey))
                // 返回redis里的值 + 1
                .map(num -> Objects.requireNonNull(redisTemplate.opsForValue().increment(redisKey)).intValue())
                // 如果redis里没有,则插入1并通过判断插入是否成功来返回初始化值1,如果插入失败,则返回拼接null
                .orElse(Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(redisKey, 1)) ? 1 : null);
    }
}

需要注意的是 RedisTemplate不能直接用new的方式来实例化,会抛出如下异常:

template not initialized; call afterPropertiesSet() before using

必须使用JavaBean实例化方式注入:

@Autowired
    private RedisTemplate redisTemplate;

 调用方法一:

NumberUtils.generateSerialNum(redisTemplate, CodeConstant.CL, CodeConstant.DATE_FORMAT, CodeConstant.FOUR);

调用方法二:

NumberUtils.generateSerialNum(redisTemplate, CodeConstant.CLS, CodeConstant.NINE);
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐