一、购物车需求分析:
1.1 购物车存储数据结构如下:
购物车实现的核心思想:
根据京东购物车的改版,我们也做成了要求登录版的购物车,即所有购物商品的用户必须登录。这使用的是cas单点登录。
1.2 数据模型Cart声明如下:
@Data@AllArgsConstructor@NoArgsConstructorpublic class Cart implements Serializable {private String sellerId; //商家idprivate String sellerName; //商家名称private List<OrderItemEntity> orderItemList; //订单项列表}
二、新建模块
zyg-cart-interface / zyg-cart-service / zyg-cart-web


说明: 1、在zyg-cart-service中引入redis的依赖就可以,其它与普通服务一样。 2、在zyg-cart-web中引入cas与security的依赖,可以参考zyg-user-web模块,将相关的单点登录的登录引入。
三、添加购物车功能的实现
3.1 在zyg-cart-service模块中定义添加到购物车的方法:
/*** ------------------------------* 功能:* 作者:WF* 微信:hbxfwf13590332912* 创建时间:2021/8/13-14:47* ------------------------------*/@Servicepublic class CartServiceImpl implements CartService {@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate ItemDao itemDao;/*** 功能: 添加商品到购物车* 参数:* 返回值: java.util.List<com.zelin.entity.group.Cart>* 时间: 2021/8/13 14:47*/@Overridepublic List<Cart> addCart(String name, Long itemId, int num) {//第一步:得到购物车列表//1.1 根据skuid得到sku商品对象ItemEntity itemEntity = itemDao.selectById(itemId);//1.2 得到商家idString sellerId = itemEntity.getSellerId();//1.3 从redis中读取购物车列表(字符串形式)String cartListString = redisTemplate.opsForValue().get(name);//1.4 将购物车列表转换为List<Cart>这种数据List<Cart> cartList = null;if(StringUtils.isBlank(cartListString)) {cartListString = "[]";}cartList = JSON.parseArray(cartListString, Cart.class);//第二步:根据itemId查询在某个购物车中是否存在此商品,有就返回此购物车//2.1 遍历购物车列表,根据sellerId查找购物车Cart cart = findCartBySellerId(cartList,sellerId);//2.2 如要没有购物车,就构造一个,有就修改购物车中的购物项集合if(cart == null){ //如果没有就创建cart = createCart(itemEntity,num);//放到购物车集合列表中cartList.add(cart);}else{ //如果有就修改此购物车//2.3 判断在此购物车的购物项集合中是否有此itemId对应的购物项OrderItemEntity orderItem = findOrderItemByItemId(cart,itemId);//2.4 如果有此购物项,就修改它的数量及金额if(orderItem != null){orderItem.setNum(orderItem.getNum() + num); //修改数量orderItem.setTotalFee(new BigDecimal(orderItem.getNum() * orderItem.getPrice().doubleValue())); //修改小计}else{ //2.5 没有此商品就创建此商品并放到购物车的购物项集合中//2.5.1 构造item对象OrderItemEntity item = createOrderItem(itemEntity, num);//2.5.2 将此item放到购物车的购物项集合中cart.getOrderItemList().add(item);}//其它一些兼容性处理//① 如果购物车中没有购物项,要从购物车列表中移除此购物项if(cart.getOrderItemList().size() == 0){cartList.remove(cart);}//② 如果某个购物车的购物项的数量为0,要从购物车的购物项中移除此购物项if(orderItem != null && orderItem.getNum() == 0){cart.getOrderItemList().remove(orderItem);}}//将购物车列表放到redis中redisTemplate.opsForValue().set(name,JSON.toJSONString(cartList),10, TimeUnit.DAYS);return cartList;}/*** 功能: 在购物车的购物项列表中查询是否指定itemid对应的购物项* 参数:* 返回值: com.zelin.entity.OrderItemEntity* 时间: 2021/8/13 15:16*/private OrderItemEntity findOrderItemByItemId(Cart cart, Long itemId) {for (OrderItemEntity itemEntity : cart.getOrderItemList()) {if (itemEntity.getItemId().longValue() == itemId.longValue()) {return itemEntity;}}return null;}/*** 功能: 创建一个新的购物车* 参数:* 返回值: com.zelin.entity.group.Cart* 时间: 2021/8/13 15:04*/private Cart createCart(ItemEntity itemEntity, int num) {//1. 创建购物车对象Cart cart = new Cart();cart.setSellerId(itemEntity.getSellerId());cart.setSellerName(itemEntity.getSeller());List<OrderItemEntity> orderItemList = new ArrayList<>();OrderItemEntity item = createOrderItem(itemEntity, num);//3. 将item放到orderItemList中orderItemList.add(item);//2. 将orderItemList设置到购物车的购物项集合cart.setOrderItemList(orderItemList);//3. 返回return cart;}/*** 功能: 创建订单项方法* 参数:* 返回值: void* 时间: 2021/8/13 15:11*/private OrderItemEntity createOrderItem(ItemEntity itemEntity, int num) {//1. 定义OrderItemEntity对象OrderItemEntity item = new OrderItemEntity();item.setGoodsId(itemEntity.getGoodsId());item.setItemId(itemEntity.getId());item.setNum(num);item.setPrice(itemEntity.getPrice());item.setTitle(itemEntity.getTitle());item.setPicPath(itemEntity.getImage());item.setTotalFee(item.getPrice().multiply(new BigDecimal(num))); //小计//2. 返回return item;}/*** 功能: 从购物车列表中根据商家id查询出购物车对象* 参数:* 返回值: com.zelin.entity.group.Cart* 时间: 2021/8/13 15:02*/private Cart findCartBySellerId( List<Cart> cartList ,String sellerId) {for (Cart cart : cartList) {if (cart.getSellerId().equals(sellerId)) {return cart;}}return null;}}
3.2 在控制器cartController中定添加到购物车方法
@Controller@RequestMapping("cart")public class CartController {@Reference(timeout = 5000)public CartService cartService;//1. 添加商品到购物车中@RequestMapping("/addCart")public String addCart(Long itemId, int num, Model model){//1.0 得到登录名String name = SecurityContextHolder.getContext().getAuthentication().getName();System.out.println("name = " + name);//1.1 将指定的sku商品添加到购物车列表中List<Cart> cartList = cartService.addCart(name,itemId,num);System.out.println("cartList = " + cartList);//1.2 将购物车集合放到model中,送到模板中显示model.addAttribute("cartList",cartList);//1.3 返回页面return "cart";}}
四、展示购物车:
4.1 前端计算购物车的总数量与总金额
<script th:inline="javascript">$(function() {//1. 得到购物车数据let cartList = [[${cartList}]];//2. 遍历购物车集合计算总金额及总数量let totalNum = 0; //商品总数量let totalMoney = 0; //商品总金额cartList.forEach(cart=>{let items = cart.orderItemList;items.forEach(item=>{totalNum += item.num;totalMoney += item.totalFee;})})//3. 为控件赋值$("#goodsNum").html(totalNum)$("#goodsPrice").html("¥" + totalMoney);})</script>
4.2 前端展示数据
<div class="toolbar"><div class="chosed">已选择<span id="goodsNum">xxx</span>件商品</div><div class="sumprice"><span><em>总价(不含运费) :</em><i class="summoney" id="goodsPrice">¥16283.00</i></span><span><em>已节省:</em><i>-¥20.00</i></span></div><div class="sumbtn"><a class="sum-btn" href="/static/cart/getOrderInfo.html" target="_blank">结算</a></div></div>
4.3 页面展示效果:


