在开发中,遇到这样一个需求,在介质资料新增时,需要生成一个介质编号,格式为"JZ+yyyyMMdd+4位递增数字"
先是使用百度找寻解决方法。解决方法
里面的查询缓存的方法在我这项目里没有,我也不会写,就自己想了个折中的方法。在请求这个接口的时候,先去数据库查询MAX(id),如果有,就在此基础上+1
如果没有,就初始化一个值1进行传参。相关代码如下:
点击查看代码
| |
| |
| public class NumberUtils { |
| |
| |
| * 生成14位唯一流水号,"JZ"+yyyyMMdd+4位数字 |
| * 4位数字,如:0001 |
| * @return |
| */ |
| @NotNull |
| public static String generateSerialNum(String str, Integer nowNum){ |
| |
| String serialNum; |
| |
| String todayDate = new SimpleDateFormat("yyyyMMdd") |
| .format(new Date()); |
| |
| String prefixCode = str + todayDate; |
| |
| serialNum = getCode(prefixCode, nowNum); |
| |
| return serialNum; |
| } |
| |
| |
| * 将数值拼接成对应的位数 |
| * @param prefix 前缀:"JZ"+yyyyMMdd |
| * @param nowNum 当前要生成的数字 |
| * @return 拼接好的流水号 |
| */ |
| private static String getCode(String prefix,int nowNum ) { |
| |
| StringBuilder code = new StringBuilder(); |
| |
| StringBuilder num = new StringBuilder(); |
| |
| AtomicInteger count = new AtomicInteger(nowNum); |
| |
| |
| if (count.get() < 10) { |
| num.append("000").append(count.get()); |
| } else if(count.get() < 100){ |
| num.append("00").append(count.get()); |
| }else if(count.get() < 1000){ |
| num.append("0").append(count.get()); |
| } else if (count.get() >= 1000) { |
| num.append(count.get()); |
| } |
| |
| |
| code.append(prefix); |
| |
| code.append(num); |
| return code.toString(); |
| } |
| } |
| |
后面被说不行,并发下不行。而且跟数据库连接效率也低。就想到了使用redis的incr方法。相关代码如下:
点击查看代码
| public class NumberUtils { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| @NotNull |
| public static String generateSerialNum(@NotNull RedisTemplate<String,Integer> redisTemplate, |
| String code, String dateFormat, Integer nums) { |
| |
| StringBuilder sb = new StringBuilder(); |
| |
| String localDateFormat = DateUtils.localDateFormat(LocalDate.now(), dateFormat); |
| sb.append(code); |
| sb.append(localDateFormat); |
| |
| |
| Integer i = redisTemplate.opsForValue().get(sb.toString()); |
| int increment; |
| if (i != null) { |
| |
| increment = Objects.requireNonNull(redisTemplate.opsForValue() |
| .increment(sb.toString())).intValue(); |
| } else { |
| |
| increment = 1; |
| redisTemplate.opsForValue().setIfAbsent(sb.toString(),increment); |
| } |
| |
| |
| sb.append(String.format(String.format("%%0%dd", nums), increment)); |
| return sb.toString(); |
| } |
| } |
然后说代码逻辑没问题,就是代码可以再优化,一通解释加我一通操作,最后代码如下:
点击查看代码
| @Slf4j |
| public class NumberUtils { |
| private NumberUtils() {} |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| @NotNull |
| public static String generateSerialNum(RedisTemplate<String,Integer> redisTemplate, |
| String code, String dateFormat, Integer nums) { |
| |
| val format = String.format("%%0%dd", nums); |
| |
| return code + DateUtils.localDateFormat(LocalDate.now(), dateFormat) |
| |
| + String.format(format, getIncrement(redisTemplate, code + DateUtils.localDateFormat(LocalDate.now(), dateFormat))); |
| } |
| |
| private static Integer getIncrement(@NotNull RedisTemplate<String,Integer> redisTemplate, String redisKey) { |
| return Optional.ofNullable(redisTemplate.opsForValue().get(redisKey)) |
| |
| .map(num -> Objects.requireNonNull(redisTemplate.opsForValue().increment(redisKey)).intValue()) |
| |
| .orElse(Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(redisKey, 1)) ? 1 : null); |
| } |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)