风萧萧兮易水寒

使用redis实现序列号工具类

前言

项目中难免会带有字符的序列号,有的是每月从1开始, 有的是每天等等.
以前也使用过存表的方式,每次获取之后加1.
这次又了解了一个.记录一下
redis为单线程,不存在线程安全问题.

序列号工具类

package com.gmaya.EurekaClient.util;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;

/**
 * 序列号工具类
 * @author GMaya
 */
@Service
public class SequenceUtil {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 获取序列号
     * 例子:假如需要获取订单号NO20200320000001等数据,前缀NO,后面的每天从1开始自增
     * 调用getCode("NO") 返回 202003200000001,0的个数根据自己业务量设置
     * 自己将返回的字符串再次拼接上NO即可!序列号 = 'NO'+getCode("NO")
     * @param keyPrefix 关键词前缀
     * @return 序列号
     */
    public String getCode(String keyPrefix) {
        // 当前日期加填充完0的值
        return new SimpleDateFormat("yyyyMMdd").format(new Date()) + getSequence(keyPrefix);
    };

    /**
     * 根据关键词前缀设置redis的key
     * @param keyPrefix
     * @return
     */
    private String getSequence(String keyPrefix) {
        // 如果你的序列号需要每个月从1开始计算,那么时间就变为yyyyMM。
        String currentDate = new SimpleDateFormat("yyyyMMdd").format(new Date());
        // 得到这个key的value值
        Long num = getIncrementNum("seq:" + keyPrefix + currentDate);
        // 填充这个值,一般情况下一天的序列号3位差不多,所以前面几位需要填充0
        return getSequence(num);
    };

    /**
     * 查询redis中这个key,并且加1返回
     * @param key
     * @return
     */
    private Long getIncrementNum(String key) {
        // 不存在准备创建 键值对
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key,
            redisTemplate.getConnectionFactory());
        Long counter = entityIdCounter.incrementAndGet(); // 自增加1
        if ((null == counter || counter.longValue() == 1)) {
            // 初始设置过期时间
            entityIdCounter.expire(2, TimeUnit.DAYS);// 单位天
        };
        return counter;
    };

    static final int DEFAULT_LENGTH = 8; // 填充0的总位数

    /**
     * 将数值前面填充0
     * @param seq
     * @return
     */
    private static String getSequence(long seq) {
        String str = String.valueOf(seq);
        int len = str.length();
        // 一般业务量不会超过8位数
        if (len >= DEFAULT_LENGTH) {
            return str;
        };
        // 前面填充0,保证数值一直是8位数
        int rest = DEFAULT_LENGTH - len;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < rest; i++) {
            sb.append('0');
        };
        sb.append(str);
        return sb.toString();
    };
};

测试

package com.gmaya.EurekaClient;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.gmaya.EurekaClient.util.SequenceUtil;

@SpringBootTest
class EurekaClientApplicationTests {

    @Autowired
    private SequenceUtil sequenceUtil;

    @Test
    public void getCode() {
        String no = "NO" + sequenceUtil.getCode("NO");
        String no2 = "NO" + sequenceUtil.getCode("NO");
        String no3 = "NO" + sequenceUtil.getCode("NO");
        String no4 = "NO" + sequenceUtil.getCode("NO");
        System.out.println(no);
        System.out.println(no2);
        System.out.println(no3);
        System.out.println(no4);
    };
};

结果:

NO2020032300000005
NO2020032300000006
NO2020032300000007
NO2020032300000008
坚持原创技术分享,您的支持将鼓励我继续创作!