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

 更新时间:2021年04月23日 15:32:56   作者:格子衫111  
这篇文章主要介绍了教你如何用Java根据日期生成流水号,文中有非常详细的代码示例,对正在学习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();
        System.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());
        //固定字母前缀 拼接 今天日期,组成新的完整的前缀,也就是缓存的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());
        //设置缓存,调用此方法,会自动将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()) / 1000;
    }
}

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

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

需要注意的是:

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

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

到此这篇关于教你如何用Java根据日期生成流水号的文章就介绍到这了,更多相关java生成流水号内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 分布式难题ElasticSearch解决大数据量检索面试

    分布式难题ElasticSearch解决大数据量检索面试

    这篇文章主要为大家介绍了分布式面试难题,ElasticSearch解决大数据量检索的问题分析回答,让面试官无话可说,帮助大家实现面试开薪自由
    2022-03-03
  • SpringBoot整合MyBatis实现CRUD操作项目实践

    SpringBoot整合MyBatis实现CRUD操作项目实践

    本文主要介绍了SpringBoot整合MyBatis实现CRUD操作项目实践,如何实现数据库的CRUD创建、读取、更新、删除操作,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • Java中StringTokenizer的用法简介汇总

    Java中StringTokenizer的用法简介汇总

    StringTokenizer 是出于兼容性的原因而被保留的遗留类(虽然在新代码中并不鼓励使用它),建议所有寻求此功能的人使用 String 的 split 方法或 java.util.regex 包,本文给大家整理了Java StringTokenizer用法,感兴趣的朋友一起看看吧
    2022-07-07
  • 解决Callable的对象中,用@Autowired注入别的对象失败问题

    解决Callable的对象中,用@Autowired注入别的对象失败问题

    这篇文章主要介绍了解决Callable的对象中,用@Autowired注入别的对象失败问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Mybatis动态SQL foreach标签用法实例

    Mybatis动态SQL foreach标签用法实例

    这篇文章主要介绍了Mybatis动态SQL foreach标签用法实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Java常用开源库汇总

    Java常用开源库汇总

    这篇文章主要介绍了Java常用开源库的相关资料,文中讲解非常细致,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-07-07
  • Restful之通用返回格式类设计

    Restful之通用返回格式类设计

    这篇文章主要介绍了Restful之通用返回格式类设计,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • 关于@Component和@Bean使用注意

    关于@Component和@Bean使用注意

    这篇文章主要介绍了关于@Component和@Bean使用注意,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • MybatisPlus逆向工程的项目实践

    MybatisPlus逆向工程的项目实践

    Mybatis-Plus逆向工程,是MP官方提供的一款代码生成器,可以自动生成对应的实体类、Mapper接口和配置文件,,本文主要介绍了MybatisPlus逆向工程的项目实践,感兴趣的可以了解一下
    2024-03-03
  • SpringBoot中接收POST参数的几种方式详解

    SpringBoot中接收POST参数的几种方式详解

    这篇文章主要介绍了SpringBoot中接收POST参数的几种方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06

最新评论