java 生成流水号 java流水号生成器 转载

发布时间 2023-08-01 18:33:45作者: sunny123456

java 生成流水号 java流水号生成器 转载
原文链接:https://blog.51cto.com/u_16099315/6331544

    生成流水线单号格式:业务码+yyyyMMdd+数字

例如: LSH2022102700001

业务码+秒级时间戳+((userId+随机数)加密)

JAVA生成编号工具类

生成流水号(格式:业务码+时间+当天自增号)

业务码+日级时间戳+(查询数据库自增)

java自动生成流水号(格式:业务码+时间+当天自增号)

业务码+日级时间戳+(查询缓存自增)

key为(业务码+日级时间戳)

过期时间为当天的剩余时间

 如何使用Java实现批量生成流水号 附详细实例代码

业务码+日级时间戳+(查询缓存自增) 实现代码

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.concurrent.TimeUnit;

/**

  • 生成流水线单号格式:业务码+yyyyMMdd+数字

  • 例如: LSH2022102700001

  • @author lyn
    /
    @Component
    public class SerialNoUtils {
    /
    *

    • 订单类别头
      */

    public static final String ORDER_CODE = "DD-";
    /**

    • 退货类别头
      */

    public static final String RETURN_ORDER = "THD-";
    /**

    • 退款类别头
      */

    public static final String REFUND_ORDER = "TKD-";
    /**

    • 序号长度
      */
      public static final int SORT_LENGTH = 6;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    /**

    • 生成17位唯一流水号,"LSH"+yyyyMMdd+6位数字
    • 6位数字,如:000001
    • @param bizCode 业务码
    • @return
      */
      public String generateSerialNo(String bizCode) {
      //定义需要返回的流水号
      String serialNo = null;
      //先查询到今天的日期,格式:"yyyyMMdd"
      String todayDate = new SimpleDateFormat("yyyyMMdd")
      .format(new Date());
      //固定字母前缀 拼接 今天日期,组成新的完整的前缀,也就是缓存的key
      String cacheKey = bizCode + todayDate;
      RLock lock = redissonClient.getLock("SerialNoLock" + cacheKey);
      //通过key查询缓存有没有num数据,没有赋初始值并设置过期时间
      try {
      lock.lock();
      if (Boolean.FALSE.equals(redisTemplate.hasKey(cacheKey))) {
      redisTemplate.opsForValue().set(cacheKey, "0", getSeconds(), TimeUnit.SECONDS);
      }
      //再通过key查询缓存有没有num数据,缓存操作根据自身项目封装工具类
      String value = redisTemplate.opsForValue().get(cacheKey);
      Long codeNum = null;
      //如果缓存查询有值,数值+1,再赋值给下一个流水号
      if (null != value) {
      codeNum = Long.parseLong(value) + 1L;
      } else {
      //如果缓存查询没值,直接赋值为1
      codeNum = 1L;
      }
      //流水号 = 缓存key + 拼接的数值 = 前缀 + 日期 + 拼接的数值
      serialNo = getCodeOfSix(cacheKey, codeNum.intValue());
      //设置缓存,调用此方法,会自动将key所对应的value+1,保存时长:今天剩余的时间
      redisTemplate.opsForValue().increment(cacheKey, 1);
      } finally {
      lock.unlock();
      }
      return serialNo;
      }

    /**

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

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

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

    • @return 拼接好的流水号
      */
      private String getCodeOfSix(String prefix, int nowNum) {

      //需要拼接的数字
      StringBuilder numSb = new StringBuilder(prefix);
      //补零
      int num = SORT_LENGTH - String.valueOf(nowNum).length();
      for (int i = 0; i < num; i++) {
      numSb.append("0");
      }
      numSb.append(nowNum);
      return numSb.toString();
      }
      /**

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

    • @return
      */
      private static int getSeconds() {
      //获取今天当前时间
      Calendar curDate = Calendar.getInstance();
      //获取明天凌晨0点的日期
      Calendar tomorrowDate = new GregorianCalendar(
      curDate.get(Calendar.YEAR),
      curDate.get(Calendar.MONTH),
      curDate.get(Calendar.DATE) + 1,
      0, 0, 0);
      //返回 明天凌晨0点 和 今天当前时间 的差值(秒数)+1000(防止提前失效)
      return (int) (tomorrowDate.getTimeInMillis() - curDate.getTimeInMillis()) / 1000 + 1000;
      }
      }