教你如何用Java根據(jù)日期生成流水號
前言
生成流水號,在企業(yè)中可以說是比較常見的需求,尤其是訂單類業(yè)務(wù)。
一般來說,需要保證流水號的唯一性。
如果沒有長度和字符的限制,那么直接使用UUID生成一個唯一字符串即可,也可以直接使用數(shù)據(jù)庫表中的主鍵,主鍵就是唯一的。
那么,如果限制了流水號必須多少位,這種怎么生成呢?
可以采用"前綴+日期+數(shù)字"的方式(ps:此方式是需要用到緩存的)
前綴:為了更好的標(biāo)識這個流水號是屬于哪種類型;
日期:為了防止重復(fù);
數(shù)字:為了表示當(dāng)前的流水所處序號。
需求:生成一個17位數(shù)的唯一流水號,“LSH”+yyyyMMdd+6位數(shù)字
代碼實(shí)現(xiàn)
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(); System.out.println("生成的流水號:"+serialNo); } /** * 生成17位唯一流水號,"LSH"+yyyyMMdd+6位數(shù)字 * 6位數(shù)字,如:000001 * @return */ private static String generateSerialNo(){ //定義需要返回的流水號 String serialNo = null; //先查詢到今天的日期,格式:"yyyyMMdd" String todayDate = new SimpleDateFormat("yyyyMMdd") .format(new Date()); //固定字母前綴 拼接 今天日期,組成新的完整的前綴,也就是緩存的key String cacheKey = "LSH"+todayDate; //再通過key查詢緩存有沒有num數(shù)據(jù),緩存操作根據(jù)自身項目封裝工具類 Long codeNum = cacheService.getCache(cacheKey, Long.class); //如果緩存查詢有值,數(shù)值+1,再賦值給下一個流水號 if (null != codeNum) { codeNum = codeNum + 1L; } else { //如果緩存查詢沒值,直接賦值為1 codeNum = 1L; } //流水號 = 緩存key + 拼接的數(shù)值 = 前綴 + 日期 + 拼接的數(shù)值 serialNo = getCodeOfSix(cacheKey, codeNum.intValue()); //設(shè)置緩存,調(diào)用此方法,會自動將key所對應(yīng)的value+1,保存時長:今天剩余的時間 cacheService.incr(cacheKey, getSeconds()); return serialNo; } /** * 將數(shù)值拼接成對應(yīng)的位數(shù) * @param prefix 前綴:"LSH"+yyyyMMdd * @param nowNum 當(dāng)前要生成的數(shù)字 * @return 拼接好的流水號 */ public static String getCodeOfSix(String prefix,int nowNum ) { //需要返回的code StringBuilder codeSb = new StringBuilder(); //需要拼接的數(shù)字 StringBuilder numSb = new StringBuilder(); //封裝的數(shù)字對象,里面 value 加了 volatile關(guān)鍵字,保證了線程安全 AtomicInteger count = new AtomicInteger(nowNum); //將數(shù)值補(bǔ)足為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); //再拼接數(shù)字 codeSb.append(numSb); return codeSb.toString(); } /** * 獲取當(dāng)天結(jié)束還剩余多少秒 * @return */ public static int getSeconds(){ //獲取今天當(dāng)前時間 Calendar curDate = Calendar.getInstance(); //獲取明天凌晨0點(diǎn)的日期 Calendar tommorowDate = new GregorianCalendar( curDate.get(Calendar.YEAR), curDate.get(Calendar.MONTH), curDate.get(Calendar.DATE) + 1, 0, 0, 0); //返回 明天凌晨0點(diǎn) 和 今天當(dāng)前時間 的差值(秒數(shù)) return (int)(tommorowDate.getTimeInMillis() - curDate .getTimeInMillis()) / 1000; } }
假如今天是2021年4月22日,運(yùn)行項目,生成的第1個流水號則為:LSH20210422000001
第2個流水號則為:LSH20210422000002,依次類推。
需要注意的是:
如果限制了位數(shù),6位數(shù)字每天最多能生成10w個流水號,所以,這個數(shù)字位數(shù)根據(jù)具體業(yè)務(wù)量進(jìn)行調(diào)整。
如果每天的生成數(shù)量量不到1w,那么使用4位數(shù)字即可。
到此這篇關(guān)于教你如何用Java根據(jù)日期生成流水號的文章就介紹到這了,更多相關(guān)java生成流水號內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
分布式難題ElasticSearch解決大數(shù)據(jù)量檢索面試
這篇文章主要為大家介紹了分布式面試難題,ElasticSearch解決大數(shù)據(jù)量檢索的問題分析回答,讓面試官無話可說,幫助大家實(shí)現(xiàn)面試開薪自由2022-03-03SpringBoot整合MyBatis實(shí)現(xiàn)CRUD操作項目實(shí)踐
本文主要介紹了SpringBoot整合MyBatis實(shí)現(xiàn)CRUD操作項目實(shí)踐,如何實(shí)現(xiàn)數(shù)據(jù)庫的CRUD創(chuàng)建、讀取、更新、刪除操作,具有一定的參考價值,感興趣的可以了解一下2024-02-02解決Callable的對象中,用@Autowired注入別的對象失敗問題
這篇文章主要介紹了解決Callable的對象中,用@Autowired注入別的對象失敗問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07Mybatis動態(tài)SQL foreach標(biāo)簽用法實(shí)例
這篇文章主要介紹了Mybatis動態(tài)SQL foreach標(biāo)簽用法實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-10-10SpringBoot中接收POST參數(shù)的幾種方式詳解
這篇文章主要介紹了SpringBoot中接收POST參數(shù)的幾種方式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06