前言
项目中难免会带有字符的序列号,有的是每月从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