教你如何用Java根据日期生成流水号

网友投稿 899 2022-10-27


教你如何用Java根据日期生成流水号

前言

生成流水号,在企业中可以说是比较常见的需求,尤其是订单类业务。

一般来说,需要保证流水号的唯一性。

如果没有长度和字符的限制,那么直接使用UUID生成一个唯一字符串即可,也可以直接使用数据库表中的主键,主键就是唯一的。

那么,如果限制了流水号必须多少位,这种怎么生成呢?

可以采用"前缀+日期+数字"的方式(ps:此方式是需要用到缓存的)

前缀:为了更好的标识这个流水号是属于哪种类型;

日期:为了防止重复;

数字:为了表示当前的流水所处序号。

需求:生成一个17位数的唯一流水号,“LSH”+yyyyMMdd+6位数字

代码实现

import java.text.SimpleDateFormat;

import java.util.Calendar;

import java.util.Date;

import java.util.GregorianCalendar;

import java.util.concurrent.atomic.AtomicInteger;

public class SerialNoTest {

public static void main(String[] args) {

String serialNo = generateSerialNo();

Systehttp://m.out.println("生成的流水号:"+serialNo);

}

/**

* 生成17位唯一流水号,"LSH"+yyyyMMdd+6位数字

* 6位数字,如:000001

* @return

*/

private static String generateSerialNo(){

//定义需要返回的流水号

String serialNo = null;

//先查询到今天的日期,格式:"yyyyMMdd"

String todayDate = new SimpleDateFormat("yyyyMMdd")

.format(new Date());

//固定字母前缀 拼接 今天日期,组成新的完整的前缀,也http://就是缓存的key

String cacheKey = "LSH"+todayDate;

//再通过key查询缓存有没有num数据,缓存操作根据自身项目封装工具类

Long codeNum = cacheService.getCache(cacheKey, Long.class);

//如果缓存查询有值,数值+1,再赋值给下一个流水号

if (null != codeNum) {

codeNum = codeNum + 1L;

} else {

//如果缓存查询没值,直接赋值为1

codeNum = 1L;

}

//流水号 = 缓存key + 拼接的数值 = 前缀 + 日期 + 拼接的数值

serialNo = getCodeOfSix(cacheKey, codeNum.intValue());http://

//设置缓存,调用此方法,会自动将key所对应的value+1,保存时长:今天剩余的时间

cacheService.incr(cacheKey, getSeconds());

return serialNo;

}

/**

* 将数值拼接成对应的位数

* @param prefix 前缀:"LSH"+yyyyMMdd

* @param nowNum 当前要生成的数字

* @return 拼接好的流水号

*/

public static String getCodeOfSix(String prefix,int nowNum ) {

//需要返回的code

StringBuilder codeSb = new StringBuilder();

//需要拼接的数字

StringBuilder numSb = new StringBuilder();

//封装的数字对象,里面 value 加了 volatile关键字,保证了线程安全

AtomicInteger count = new AtomicInteger(nowNum);

//将数值补足为6位字符串

if (count.get() < 10) {

numSb.append("00000").append(count.get());

} else if(count.get() < 100){

numSb.append("0000").append(count.get());

}else if(count.get() < 1000){

numSb.append("000").append(count.get());

}else if(count.get() < 10000){

numSb.append("00").append(count.get());

}else if(count.get() < 100000){

numSb.append("0").append(count.get());

} else if (count.get() >= 100000) {

numSb.append(count.get());

}

//先拼接前缀

codeSb.append(prefix);

//再拼接数字

codeSb.append(numSb);

return codeSb.toString();

}

/**

* 获取当天结束还剩余多少秒

* @return

*/

public static int getSeconds(){

//获取今天当前时间

Calendar curDate = Calendar.getInstance();

//获取明天凌晨0点的日期

Calendar tommorowDate = new GregorianCalendar(

curDate.get(Calendar.YEAR),

curDate.get(Calendar.MONTH),

curDate.get(Calendar.DATE) + 1,

0, 0, 0);

//返回 明天凌晨0点 和 今天当前时间 的差值(秒数)

return (int)(tommorowDate.getTimeInMillis() - curDate .getTimeInMillis(EDZUZum)) / 1000;

}

}

假如今天是2021年4月22日,运行项目,生成的第1个流水号则为:LSH20210422000001

第2个流水号则为:LSH20210422000002,依次类推。

需要注意的是:

如果限制了位数,6位数字每天最多能生成10w个流水号,所以,这个数字位数根据具体业务量进行调整。

如果每天的生成数量量不到1w,那么使用4位数字即可。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:WLAN 无线网络 10 - 控制帧和数据帧
下一篇:Cisco 1841 PPPOE配置
相关文章

 发表评论

暂时没有评论,来抢沙发吧~