作者:一枝花算不算浪漫
出处:https://www.cnblogs.com/wang-meng/
提交订单有几个关键点:
1, 用户必须登录
2, 购物车必须要有购物项
3, 购物车中购物项库存必须小于库存
4, 结算成功, 清理购物车(这个只清理购物车中已经结算的购物项)
接下来我们再来看下订单相关的两张表的设计:
订单表
订单详情表
在这里我们可以发现 订单表和 我们的购物车很像, 订单详情表和我们的购物车中的购物项很像. 明白了这些原理后我们就来看下代码的具体实现.
我们来先写Service层的方法: CartServiceImpl.java
@Autowired
private OrderDao orderDao;
@Autowired
private DetailDao detailDao;
//保存订单
public void insertOrder(Order order, String username){
//订单ID
Long id = jedis.incr("oid");
order.setId(id);
//用户id
String buyerId = jedis.get(username);
order.setBuyerId(Long.parseLong(buyerId));
BuyerCart buyerCart = selectBuyerCartFromRedis(username);
List<BuyerItem> items = buyerCart.getItems();
for (BuyerItem item : items) {
item.setSku(selectSkuById(item.getSku().getId()));
}
//运费, 由运费提供
order.setDeliverFee(buyerCart.getFee());
//订单总金额, 由购物车提供
order.setTotalPrice(buyerCart.getTotalPrice());
//订单金额, 由购物车提供
order.setOrderPrice(buyerCart.getProductPrice());
//支付状态: 0到付 1待付款 2已付款 3待退款 4退款成功 5退款失败
if (order.getPaymentWay() == 1) {
order.setIsPaiy(0);
}else {
//我们这里页面上只有 两种选择: 0到付 1待付款
order.setIsPaiy(1);
}
//订单状态: 0提交订单 1仓库配货 2商品出库 3等待收货 4完成 5待退货 6已退货
order.setOrderState(0);
//订单生成时间
order.setCreateDate(new Date());
//生成订单
orderDao.insertSelective(order);
//保存订单详情
for (BuyerItem item : items) {
Detail detail = new Detail();
//订单详情表
/*
* ID:自增长
* 订单ID, 商品编号ID, 商品名称, 颜色中文名称, 尺码, 价格, 数量, 购物车中购物项提交数量
*/
detail.setOrderId(id);
detail.setProductId(item.getSku().getProductId());
detail.setProductName(item.getSku().getProduct().getName());
detail.setColor(item.getSku().getColor().getName());
detail.setSize(item.getSku().getSize());
detail.setPrice(item.getSku().getPrice());
detail.setAmount(item.getAmount());
//保存购物车中购物项
detailDao.insertSelective(detail);
//减库存
//清空购物车, 这里只写全部删除的方法, 如果删除某个购物项需使用jedis.hdel();
jedis.del("buyerCart:" + username);
}
}
这里 是利用Redis生成主键ID, 我们前面也有对比过Redis生成主键和数据库生成主键 以及UUID的对比, 这里就不再细说了.
剩下的就是取购物车, 在这里我们可以通过username去取出skuId和购买数量amount, 因为我们在Redis存储的表名就是"buyerCart:"+username就是key是:skuId , value是amount.
剩下的就是将购物车中的内容装配到Order中即可.
接着来看下 Controller层的代码: CartController.java:
//去结算
@RequestMapping(value="/buyer/trueBuy")
public String trueBuy(String[] skuIds, Model model, HttpServletRequest request, HttpServletResponse response){
//1, 购物车必须有商品,
//取出用户名 再取出购物车
String username = sessionProviderService.getAttributterForUsername(RequestUtils.getCSessionId(request, response));
//取出所有购物车
BuyerCart buyerCart = cartService.selectBuyerCartFromRedisBySkuIds(skuIds, username);
List<BuyerItem> items = buyerCart.getItems();
if (items.size() > 0) {
//购物车中有商品
//判断所勾选的商品是否都有货, 如果有一件无货, 那么就刷新页面.
Boolean flag = true;
//2, 购物车中商品必须有库存 且购买大于库存数量时视为无货. 提示: 购物车原页面不动. 有货改为无货, 加红提醒.
for (BuyerItem buyerItem : items) {
//装满购物车的购物项, 当前购物项只有skuId这一个东西, 我们还需要购物项的数量去判断是否有货
buyerItem.setSku(cartService.selectSkuById(buyerItem.getSku().getId()));
//校验库存
if (buyerItem.getAmount() > buyerItem.getSku().getStock()) {
//无货
buyerItem.setIsHave(false);
flag = false;
}
if (!flag) {
//无货, 原页面不动, 有货改成无货, 刷新页面.
model.addAttribute("buyerCart", buyerCart);
return "cart";
}
}
}else {
//购物车没有商品
//没有商品: 1>原购物车页面刷新(购物车页面提示没有商品)
return "redirect:/shopping/toCart";
}
//3, 正常进入下一个页面
return "order";
}
//提交订单
@RequestMapping(value="/buyer/submitOrder")
public String submitOrder(Order order, HttpServletRequest request, HttpServletResponse response){
String username = sessionProviderService.getAttributterForUsername(RequestUtils.getCSessionId(request, response));
//保存订单
cartService.insertOrder(order, username);
return "success";
}
最完整的购物车实现及原理(仿京东实现原理), 对于"/buyer/"这样格式的请求我们的springmvc都会拦截, 拦截的形式 就是判断用户是否登录. 这里我们也不会详细说明.
这里要判断购物项中的数量是否大于库存, 如果大于库存就刷新购物车页面, 且显示该购物项无货状态.
剩下的提交订单 就是保存order到订单表, 这里面也包含保存购物详情到订单详情表.
推荐作品
● 程序员提高技术的资源汇总
● MySQL误删数据,再也不用跑路了