1. controller处理异常
/**
* 锁定库存,下单后需要把库存锁定
* @param vo
* @return
*/
@PostMapping("/lock/order")
public R orderLockStock(@RequestBody WareSkuLockVo vo){
try {
wareSkuService.orderLockStock(vo);
return R.ok();
} catch (NoStockException e) {
log.warn("\n" + e.getMessage());
}
return R.error(BizCodeEnume.NO_STOCK_EXCEPTION.getCode(), BizCodeEnume.NO_STOCK_EXCEPTION.getMsg());
}
2.定义异常类
/**
* @Description 库存异常。
**/
public class NoStockException extends RuntimeException {
@Getter @Setter
private Long skuId;
public NoStockException(Long skuId) {
super("商品id:"+ skuId + "库存不足!");
}
public NoStockException(String msg) {
super(msg);
}
}
3. service抛出异常
@Transactional(rollbackFor = NoStockException.class) //默认:只要是运行时异常均会回滚,所以如果不写(rollbackFor = NoStockException.class) 也可以的。
@Override
public Boolean orderLockStock(WareSkuLockVo vo) {
// 当定库存之前先保存订单 以便后来消息撤回
WareOrderTaskEntity taskEntity = new WareOrderTaskEntity();
taskEntity.setOrderSn(vo.getOrderSn());
orderTaskService.save(taskEntity);
// [理论上]1. 按照下单的收获地址 找到一个就近仓库, 锁定库存
// [实际上]1. 找到每一个商品在那个一个仓库有库存
List<OrderItemVo> locks = vo.getLocks();
List<SkuWareHasStock> collect = locks.stream().map(item -> {
SkuWareHasStock hasStock = new SkuWareHasStock();
Long skuId = item.getSkuId();
hasStock.setSkuId(skuId);
// 查询这个商品在哪有库存
List<Long> wareIds = wareSkuDao.listWareIdHasSkuStock(skuId);
hasStock.setWareId(wareIds);
hasStock.setNum(item.getCount());
return hasStock;
}).collect(Collectors.toList());
//多订库存
for (SkuWareHasStock hasStock : collect) {
Boolean skuStocked = true;
Long skuId = hasStock.getSkuId();
List<Long> wareIds = hasStock.getWareId();
if(wareIds == null || wareIds.size() == 0){
// 没有任何仓库有这个库存
throw new NoStockException(skuId.toString());
}
// 如果每一个商品都锁定成功 将当前商品锁定了几件的工作单记录发送给MQ
// 如果锁定失败 前面保存的工作单信息回滚了-也没关系,由于去数据库查不到id也无妨
for (Long wareId : wareIds) {
// 成功就返回 1 失败返回0
Long count = wareSkuDao.lockSkuStock(skuId, wareId, hasStock.getNum());
if(count == 1){
// TODO 告诉MQ库存锁定成功 一个订单锁定成功 消息队列就会有一个消息
//WareOrderTaskDetailEntity detailEntity = new WareOrderTaskDetailEntity(null,skuId,"",hasStock.getNum() ,taskEntity.getId(),wareId,1);
WareOrderTaskDetailEntity detailEntity = new WareOrderTaskDetailEntity(null,skuId,"",hasStock.getNum(),taskEntity.getId(),wareId,1);
orderTaskDetailService.save(detailEntity); //入库
StockLockedTo stockLockedTo = new StockLockedTo();
stockLockedTo.setId(taskEntity.getId());
StockDetailTo detailTo = new StockDetailTo();
BeanUtils.copyProperties(detailEntity, detailTo);
// 防止回滚以后找不到数据 把详细信息页
stockLockedTo.setDetailTo(detailTo);
rabbitTemplate.convertAndSend(eventExchange, routingKey ,stockLockedTo);
skuStocked = false;
break;
}
// 当前仓库锁定失败 重试下一个仓库
}
if(skuStocked){
// 当前商品在所有仓库都没锁柱
throw new NoStockException(skuId.toString());
}
}
// 3.全部锁定成功
return true;
}
特别注意:
throw new NoStockException(skuId.toString()); 无库存了。
此时返回页面无库存提示。