下订单业务逻辑:
1、验证用户重复提交订单
1
2
3
|
redis中有一个订单流水号,
哪个线程先到,就判断并删除流水号key,(使用lua脚本保证原子性)
删除成功,业务逻辑往下走。
|
2、验证表单参数是否空
3、校验价格变化
1
2
3
4
5
6
7
8
9
10
11
12
|
1.先获取订单项的所有id
2.远程调用,获取所有id的sku的最新价格
3.比较价格
3.1 转换成map,key为skuid,值为价格
3.2 比较订单项的价格和map中的价格
3.3 价格不相等
远程调用更行购物车最新价格。
抛异常。
3.4 价格相等,业务流程继续往下走
|
4、校验库存锁定库存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
远程调用 检查并锁定库存
1. 防止重复请求
在redis中setNx一把锁,
如果存在,则已执行过库存锁定
返回空字符串(成功)
不存在,添加成功。业务往下走
2. 遍历所有商品,验库存
满足条件:
商品的available_num > skuNum
不满足的将 skuLockVo.setIsHaveStock(false);
遍历所有商品,锁库存
检查所所有商品的IsHaveStock
只要有一个商品的IsHaveStock是false,抛异常。
//锁定失败,解除
redisTemplate.delete(key);
// 响应锁定状态
return result.toString();
否则,锁库存(也就是修改表里的可用库存和锁定库存)-->available_num-,lock_num+
//锁定库存 挨个遍历,修改数据库
skuLockVoList.forEach(skuLockVo -> {
int row = skuStockMapper.lock(skuLockVo.getSkuId(), skuLockVo.getSkuNum());
if(row == 0) {//受影响行数为0,修改失败
//解除去重
redisTemplate.delete(key);
throw new ServiceException("库存锁定失败");
}
});
3.
// 如果所有商品都锁定成功的情况下,需要缓存锁定信息到redis。以方便将来解锁库存 或者 减库存
redisTemplate.opsForValue().set(dataKey, skuLockVoList);
|
5、保存订单(订单表、订单项表、订单日志表)
1
2
3
4
5
6
7
8
9
|
Long orderId = null;
try {
//下单
orderId = this.saveOrder(orderForm);
} catch (Exception e) {
e.printStackTrace();
//抛出异常
throw new ServiceException("下单失败");
}
|
6、删除购物车选中商品
远程调用 删除购物车选中商品信息
1
2
3
4
5
6
7
8
|
R<Boolean> booleanR = remoteCartService.deleteCartCheckedList(userId, SecurityConstants.INNER);
if (R.FAIL == booleanR.getCode()) {
throw new ServiceException(booleanR.getMsg());
}
Boolean isDeleteCart = booleanR.getData();
if (!isDeleteCart) {
throw new ServiceException("购物车商品删除失败!!");
}
|