这儿有一个基于redis生成订单流水号的工具,拿走不谢!
1 import cn.hutool.core.util.RandomUtil; 2 import cn.hutool.core.util.StrUtil; 3 import lombok.extern.slf4j.Slf4j; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.data.redis.core.RedisTemplate; 6 import org.springframework.data.redis.core.script.DefaultRedisScript; 7 import org.springframework.lang.Nullable; 8 import org.springframework.stereotype.Component; 9 10 import java.time.LocalDateTime; 11 import java.time.format.DateTimeFormatter; 12 import java.util.Collections; 13 import java.util.concurrent.TimeUnit; 14 15 /** 16 * 生成订单流水号18 * 精确到秒级,后面加随机数(redis获取) 19 * <p> 20 * 变更记录:2023-12-13 14:10 gz.zhang 通过增加随机性,修正因宿主机时钟回拨导致生成重复值的bug 21 * 变更记录:2023-12-19 14:37 刘红洁/张国战 ①key改为按日期,最后的拼接用取模的方式防止数据越界,②解决concat带来的bug。 22 * 23 * @author wangzaizhou 24 */ 25 @Component 26 @Slf4j 27 public class GenerateOrderIdUtil { 28 private static final String DEFAULT_KEY_PREFIX = "keyPrefix"; 29 private static RedisTemplate<String, Object> stringObjectRedisTemplate; 30 31 @Autowired 32 public void setRedisUtil(RedisTemplate<String, Object> redisTemplate) { 33 stringObjectRedisTemplate = redisTemplate; 34 } 35 36 /** 37 * 订单流水号组成: 时间秒 + 5位数(redis计算后的) 38 * 39 * @param keyPrefix redis key的前缀标识,可以指定为 系统标识(如“Channel”),也可以指定为业务标识(如“Pay”),或者具体数据标识(如“PayPaymentFlow”),etc.,也可为空 40 * @return 2021030914590406391 41 */ 42 public static long genOrderId(@Nullable String keyPrefix) { 43 if (StrUtil.isBlank(keyPrefix)) { 44 keyPrefix = DEFAULT_KEY_PREFIX; 45 } 46 LocalDateTime now = LocalDateTime.now(); 47 String redisKey = keyPrefix + now.format(DateTimeFormatter.ofPattern("yyyyMMdd")); 48 Long incrValue = null; 49 try { 50 incrValue = stringObjectRedisTemplate.execute(REDIS_SCRIPT, Collections.singletonList(redisKey), TimeUnit.HOURS.toSeconds(24)); 51 } catch (Exception e) { 52 log.error("GenerateOrderIdUtil 生成订单流水号异常,keyPrefix={}", keyPrefix, e); 53 } 54 if (incrValue == null) incrValue = RandomUtil.randomLong(99999); 55 String orderIdPrefix = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); 56 String orderId = String.format("%s%05d", orderIdPrefix, incrValue % 100000); 57 return Long.parseLong(orderId); 58 } 59 60 /** 61 * 订单流水号组成: 时间秒 + 5位数(redis计算后的) 62 * 63 * @return 2021030914590406391 64 */ 65 public static long genOrderId() { 66 return genOrderId(DEFAULT_KEY_PREFIX); 67 } 68 69 private final static DefaultRedisScript<Long> REDIS_SCRIPT = new DefaultRedisScript<>( 70 "local key = KEYS[1]\n" + 71 "local expiration_time = (ARGV[1])\n" + 72 73 "local current_value = redis.call('INCRBY', key, 1)\n" + 74 "if current_value == 1 then\n" + 75 " redis.call('EXPIRE', key, expiration_time)\n" + 76 "end\n" + 77 "return current_value\n" 78 , Long.class); 79 80 }
当看到一些不好的代码时,会发现我还算优秀;当看到优秀的代码时,也才意识到持续学习的重要!--buguge
本文来自博客园,转载请注明原文链接:https://www.cnblogs.com/buguge/p/17914586.html
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
· 全程使用 AI 从 0 到 1 写了个小工具
2015-12-19 ASP.NET将原始图片按照指定尺寸等比例缩放显示图片