前言
订单号具有唯一标识符的作用,下边将演示自增、随机、组合的方式,生成高效、安全、唯一的订单号,以满足业务需求和避免潜在问题。
自增
自增常见的有:纯数字自增、时间+数字自增、数据库主键id自增
纯数字自增
需求:生成8位自增数字的订单号,不足8位前缀补0。
实现:使用redis的incr函数完成此需求。
@RestController
@RequestMapping("/testOrderCode")
public class TestOrderCodeController {
@Resource
private RedisTemplate<String, Integer> redisTemplate;
private static final String TEST_ORDER_CODE_KEY = "test_order_code_key";
@GetMapping("/test")
public String test() {
//使用incr获取自增的订单号
Long increment = redisTemplate.opsForValue().increment(TEST_ORDER_CODE_KEY);
//将订单号不足8位前缀补0,"%08d",%0表示前缀补0,8表示补充8位,d表示数字类型
String oderCode = String.format("%08d", increment);
return oderCode;
}
}
输出结果:00000001
时间+数字自增
需求:使用年月日(yyMMdd)当订单号前缀,后四位使用当日订单号自增。
实现:获取yyMMdd格式的时间字符串,然后将该字符串作为redis的key使用,并给该key设置一天的过期时间。后四位数字自增使用redis的 incr函数实现。
@RestController
@RequestMapping("/testOrderCode")
public class TestOrderCodeController {
@Resource
private RedisTemplate<String, Integer> redisTemplate;
private static final String TEST_ORDER_CODE_KEY = "test_order_code_key";
@GetMapping("/test")
public String test() {
// 定义日期格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMdd");
//根据当前时间获取yyMMdd格式的时间字符串
String format = LocalDate.now().format(formatter);
//判断是否存在key,不存在则设置1天的过期时间
if (Boolean.FALSE.equals(redisTemplate.hasKey(format))) {
redisTemplate.expire(format, 1, TimeUnit.DAYS);
}
//使用incr获取自增的订单号
Long increment = redisTemplate.opsForValue().increment(format);
//将订单号不足4位前缀补0,"%04d",%0表示前缀补0,4表示补充4位,d表示数字类型
String oderCode = String.format("%04d", increment);
return format + oderCode;
}
}
输出结果:2412260001
数据库主键id自增
需求:生成8位自增数字的订单号,不足8位前缀补0。
实现:使用数据库自增主键实现该需求。先保存订单到数据库,取订单id,再将id前缀补0操作后更新到数据库中。
@RestController
@RequestMapping("/testOrderCode")
public class TestOrderCodeController {
@Resource
private OrdersMapper orderMapper;
@GetMapping("/test")
public String test() {
//保存订单,并获取id
OrdersDO ordersDO = new OrdersDO();
orderMapper.insert(ordersDO);
Long id = ordersDO.getId();
//将订单号不足8位前缀补0,"%08d",%0表示前缀补0,8表示补充8位,d表示数字类型
String oderCode = String.format("%08d", id);
//更新订单号
orderMapper.updateById(ordersDO.setOrderCode(oderCode));
return oderCode;
}
}
输出结果:00000001
随机
随机常见的有:随机数、UUID、分布式全局唯一id(雪花算法)
随机数
需求:生成随机的订单号。
实现:使用Random生成随机数。
import cn.hutool.core.util.RandomUtil;
@RestController
@RequestMapping("/testOrderCode")
public class TestOrderCodeController {
@Resource
private OrdersMapper orderMapper;
@GetMapping("/test")
public String test() {
// 定义日期格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMdd");
//根据当前时间获取yyMMdd格式的时间字符串
String format = LocalDate.now().format(formatter);
//生成随机8位数字
String random = RandomUtil.randomNumbers(8);
//时间+随机数组成订单号
String oderCode = format + random;
//判断生成的订单号在数据库中是否存在,如果存在则继续随机生成订单号
while (orderMapper.selectCount(Wrappers.lambdaQuery(OrdersDO.class).eq(OrdersDO::getOrderCode, oderCode)) > 0){
oderCode = format + RandomUtil.randomNumbers(8);
}
return oderCode;
}
}
输出结果:24122683230048
UUID
需求:生成随机的订单号。
实现:使用UUID实现该需求。
import java.util.UUID;
@RestController
@RequestMapping("/testOrderCode")
public class TestOrderCodeController {
@GetMapping("/test")
public String test() {
// 生成一个UUID
UUID uuid = UUID.randomUUID();
// 将UUID转换为字符串,并移除分隔符
String oderCode = uuid.toString().replace("-", "");
return oderCode;
}
}
输出结果:8a45cd3458b640789ed3c9ef223d090b
分布式全局唯一id(雪花算法)
需求:生成随机的订单号。
实现:使用分布式全局唯一id(雪花算法)实现该需求。
import cn.hutool.core.lang.Snowflake;
@RestController
@RequestMapping("/testOrderCode")
public class TestOrderCodeController {
@GetMapping("/test")
public String test() {
// 创建一个雪花算法ID生成器实例,通常你需要指定终端ID和数据中心ID
Snowflake snowflake = new Snowflake(1, 1);
String oderCode = snowflake.nextIdStr();
return oderCode;
}
}
输出结果:1872140136729415680
结语
如有问题,还望告知。不胜感激!
这篇文章对你有帮助的话,动动你可爱的小手指,点个赞再走吧。非常感谢!