目录
秒杀系统要调用订单微服务中的下订单功能,所以将原来的订单微服务进行重构。
一、目录结构
将原来的pojo抽取到interface中,并且增加orderApi接口:
package com.leyou.order.api;
import com.leyou.order.pojo.Order;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
* @Author: 98050
* @Time: 2018-11-12 15:13
* @Feature: 订单服务接口
*/
@RequestMapping("order")
public interface OrderApi {
/**
* 创建订单
* @param seck
* @param order
* @return
*/
@PostMapping
ResponseEntity<List<Long>> createOrder(@RequestParam("seck") String seck, @RequestBody @Valid Order order);
}
二、修改创建订单方法
要判断是普通订单还是秒杀订单,通过传入的seck来判断,还有就是以前的方法没有修改库存。。。。。。。。。。。。。。。。。。。。
2.1 Controller
/**
* 创建订单
* @param order 订单对象
* @return 订单编号
*/
@PostMapping
@ApiOperation(value = "创建订单接口,返回订单编号",notes = "创建订单")
@ApiImplicitParams({
@ApiImplicitParam(name = "order",required = true,value = "订单的json对象,包含订单条目和物流信息"),
@ApiImplicitParam(name = "tag",required = true,value = "是否是秒杀订单")
})
public ResponseEntity<List<Long>> createOrder(@RequestParam("seck") String seck,@RequestBody @Valid Order order){
System.out.println(seck);
List<Long> skuId = this.orderService.queryStock(seck,order);
if (skuId != null && skuId.size() != 0){
//库存不足
return new ResponseEntity<>(skuId,HttpStatus.OK);
}
Long id = this.orderService.createOrder(seck,order);
return new ResponseEntity<>(Arrays.asList(id), HttpStatus.CREATED);
}
2.2 库存检查
在下订单前先对订单中的商品库存进行检验,如果库存余量不足,那么就直接返回对应的商品id。
orderService中添加方法queryStock:
/**
* 查询订单下商品的库存,返回库存不足的商品Id
* @param order
* @return
*/
@Override
public List<Long> queryStock(String tag,Order order) {
String seck = "seckill";
List<Long> skuId = new ArrayList<>();
order.getOrderDetails().forEach(orderDetail -> {
Stock stock = this.stockMapper.selectByPrimaryKey(orderDetail.getSkuId());
if (stock.getStock() - orderDetail.getNum() < 0){
//先判断库存是否充足
skuId.add(orderDetail.getSkuId());
}else{
//充足的话就判断秒杀库存是否充足
if (StringUtils.isNotEmpty(tag) && seck.equals(tag)){
//检查秒杀库存
if (stock.getSeckillStock() - orderDetail.getNum() < 0){
skuId.add(orderDetail.getSkuId());
}
}
}
});
return skuId;
}
2.3 创建订单
@Transactional(rollbackFor = Exception.class)
@Override
public Long createOrder(String tag,Order order) {
//1.生成orderId
long orderId = idWorker.nextId();
//2.获取登录的用户
UserInfo userInfo = LoginInterceptor.getLoginUser();
//3.初始化数据
order.setBuyerNick(userInfo.getUsername());
order.setBuyerRate(false);
order.setCreateTime(new Date());
order.setOrderId(orderId);
order.setUserId(userInfo.getId());
//4.保存数据
this.orderMapper.insertSelective(order);
//5.保存订单状态
OrderStatus orderStatus = new OrderStatus();
orderStatus.setOrderId(orderId);
orderStatus.setCreateTime(order.getCreateTime());
//初始状态未未付款:1
orderStatus.setStatus(1);
//6.保存数据
this.orderStatusMapper.insertSelective(orderStatus);
//7.在订单详情中添加orderId
order.getOrderDetails().forEach(orderDetail ->{
//添加订单
orderDetail.setOrderId(orderId);
});
//8.保存订单详情,使用批量插入功能
this.orderDetailMapper.insertList(order.getOrderDetails());
//9.更新库存
order.getOrderDetails().forEach(orderDetail -> this.stockMapper.reduceStock(orderDetail.getSkuId(),orderDetail.getNum()));
//10.如果是秒杀订单,那么修改秒杀商品库存
String seck = "seckill";
if (StringUtils.isNotEmpty(tag) && tag.equals(seck)){
order.getOrderDetails().forEach(orderDetail -> this.stockMapper.reduceSeckStock(orderDetail.getSkuId(),orderDetail.getNum()));
}
logger.debug("生成订单,订单编号:{},用户id:{}", orderId, userInfo.getId());
return orderId;
}
在stockMapper中增加方法reduceStock和rdeuceSeckStock:
库存stock一定要大于0,不能为负。
package com.leyou.order.mapper;
import com.leyou.item.pojo.Stock;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import tk.mybatis.mapper.common.Mapper;
/**
* @Author: 98050
* @Time: 2018-11-10 17:58
* @Feature:
*/
public interface StockMapper extends Mapper<Stock> {
/**
* 更新对应商品的库存,且库存必须大于0,否则回滚。
* @param skuId
* @param num
*/
@Update("update tb_stock set stock = stock - #{num} where sku_id = #{skuId} and stock > 0")
void reduceStock(@Param("skuId") Long skuId, @Param("num") Integer num);
/**
* 更新对应商品的秒杀库存,且库存必须大于0,否则回滚。
* @param skuId
* @param num
*/
@Update("update tb_stock set seckill_stock = seckill_stock - #{num} where sku_id = #{skuId} and seckill_stock > 0")
void reduceSeckStock(@Param("skuId")Long skuId, @Param("num")Integer num);
}
三、前端修改
修改getOrderInfo.html页面中的订单提交方法:
根据返回的状态码来判断库存是否充足。返回数据是一个列表,所以就不用修改回调(避免long类型数据异常)。