document
API test

获取购物车详情

POST

Description or Example

# Bug修复 ## postHandle的空指针异常 > 这是因为没有初始化isExistsTempUser这个属性导致的空指针异常, 因此, 需要初始化为false # 核心源码 ```java @GetMapping("/cart.html") public ModelAndView cartIndex(ModelAndView mv) { // 获取用户的购物车 CartVO cartVO = cartService.getCart(); // 把用户的购物车放在请求域里面 mv.addObject("cart", cartVO); mv.setViewName("cartList"); return mv; } ``` ```java @Override public CartVO getCart() { // 获取对hash的操作对象 BoundHashOperations<String, Object, Object> hashHandle = getHashHandle(); // 首先我们需要判断, 是否登陆过, 如果没有登陆过, 则没有购物车合并之说 UserBO userBO = CartInterceptor.USER_INFO_ID.get(); Long userId = userBO.getUserId(); String userKey = userBO.getUserKey(); CartVO cartVO = new CartVO(); // 创建一个购物车对象 if (userId == null) { // 尚未登录, 未登录, 直接将整个购物车查询出来 return cartVO.setCartItemVOS(getAllCartItems(hashHandle)).setReduce(new BigDecimal(0)); }else { // 已经登录了, 需要判断离线购物车是否存在购物项, 如果存在需要合并 // 首先获取离线购物车操作 BoundHashOperations<String, Object, Object> offLineHashHandle = getHashHandle(false, true); if (offLineHashHandle.size() > 0L) { // 离线购物车有东西, 需要合并 List<CartItemVO> offLineCartItems = getAllCartItems(offLineHashHandle); this.addCartItems(hashHandle, offLineCartItems); // 合并完了之后, 需要清空购物车 this.flushOffLineCart(userKey); } // 无论是否需要合并, 最后都需要获取在线购物车的数据 return cartVO.setCartItemVOS(getAllCartItems(hashHandle)).setReduce(new BigDecimal(0L)); } } /** * 直接删除离线购物车 * @param userKey */ private void flushOffLineCart(String userKey) { redisTemplate.delete(CART_PREFIX + userKey); } /** * 批量添加购物项 * @param hashHandle * @param offLineCartItems */ private void addCartItems(BoundHashOperations<String, Object, Object> hashHandle, List<CartItemVO> offLineCartItems) { for (CartItemVO offLineCartItem : offLineCartItems) { String cartKey = offLineCartItem.getSkuId().toString(); // 获取对应的key Object cartItemJson = hashHandle.get(cartKey); if (cartItemJson != null) { // 该购物项存在了, 需要做累加 CartItemVO cartItemVO = JSON.parseObject((String) cartItemJson, CartItemVO.class); hashHandle.put(cartItemVO.getSkuId().toString(), JSON.toJSONString(cartItemVO.setCount(cartItemVO.getCount() + offLineCartItem.getCount()))); }else { // 否则不存在, 直接添加 hashHandle.put(offLineCartItem.getSkuId().toString(), JSON.toJSONString(offLineCartItem)); } } } /** * 获取所有的购物项并且赋值 * @param hashHandle * @param cartVO */ private List<CartItemVO> getAllCartItems(BoundHashOperations<String, Object, Object> hashHandle) { List<Object> cartItems = hashHandle.values(); // 获取所有的购物项 if (cartItems != null && !cartItems.isEmpty()) { return cartItems.stream() .map(cartItem -> JSON.parseObject((String) cartItem, CartItemVO.class)) .collect(Collectors.toList()); } return null; } /** * 该方法主要是给用户最优选择, 如果登陆了选择在线购物车, 否则离线 * @return */ private BoundHashOperations<String, Object, Object> getHashHandle() { // 判断是否登录, 如果登录了使用在线购物车, 否则使用离线购物车 return CartInterceptor.USER_INFO_ID.get().getUserId() != null ? getHashHandle(true, false) : getHashHandle(false, true); } private BoundHashOperations<String, Object, Object> getHashHandle(boolean isOnline, boolean isOffline) { if (isOnline && isOffline || !isOnline && !isOffline) { // 如果在线和离线同时选, 抛异常 throw new RuntimeException("只能获取在线购物车或离线购物车的单一操作, 不能同时获取"); } UserBO userBO = CartInterceptor.USER_INFO_ID.get(); Long userId = userBO.getUserId(); String userKey = userBO.getUserKey(); if (isOnline) { return redisTemplate.boundHashOps(CART_PREFIX + userId); } return redisTemplate.boundHashOps(CART_PREFIX + userKey); } ``` # 知识点 ## 利用直接添加购物项有什么问题(之前的方法)? > 最大的问题是远程调用微服务, 因为主要目的是让离线购物车的数据合并到在线, 相关的数据已知, 不需要从结果的一部分推断结果, 效率很差, 因此, 不能直接调用 > 而且, 不要忘记清空离线购物车