一.购物车工程搭建
>创建e3-cart聚合工程以及下面的子模块,还有e3-cart-web工程,全部参照其他已有的工程实现
二.添加购物车-代码实现
1 @Value("${COOKIE_CART_EXPIRE}") 2 private Integer COOKIE_CART_EXPIRE; 3 4 @Autowired 5 private ItemService itemService; 6 @Autowired 7 private CartService cartService; 8 9 @RequestMapping("/cart/add/{itemId}") 10 public String addCart(@PathVariable Long itemId, @RequestParam(defaultValue="1")Integer num, 11 HttpServletRequest request, HttpServletResponse response) {22 //从cookie中取购物车列表 23 List<TbItem> cartList = getCartListFromCookie(request); 24 //判断商品在商品列表中是否存在 25 boolean flag = false; 26 for (TbItem tbItem : cartList) { 27 //如果存在数量相加 28 if (tbItem.getId() == itemId.longValue()) { 29 flag = true; 30 //找到商品,数量相加 31 tbItem.setNum(tbItem.getNum() + num); 32 //跳出循环 33 break; 34 } 35 } 36 //如果不存在 37 if (!flag) { 38 //根据商品id查询商品信息。得到一个TbItem对象 39 TbItem tbItem = itemService.getItemById(itemId); 40 //设置商品数量 41 tbItem.setNum(num); 42 //取一张图片 43 String image = tbItem.getImage(); 44 if (StringUtils.isNotBlank(image)) { 45 tbItem.setImage(image.split(",")[0]); 46 } 47 //把商品添加到商品列表 48 cartList.add(tbItem); 49 } 50 //写入cookie 51 CookieUtils.setCookie(request, response, "cart", JsonUtils.objectToJson(cartList), COOKIE_CART_EXPIRE, true); 52 //返回添加成功页面 53 return "cartSuccess"; 54 } 55 56 /** 57 * 从cookie中取购物车列表的处理 58 * <p>Title: getCartListFromCookie</p> 59 * <p>Description: </p> 60 * @param request 61 * @return 62 */ 63 private List<TbItem> getCartListFromCookie(HttpServletRequest request) { 64 String json = CookieUtils.getCookieValue(request, "cart", true); 65 //判断json是否为空 66 if (StringUtils.isBlank(json)) { 67 return new ArrayList<>(); 68 } 69 //把json转换成商品列表 70 List<TbItem> list = JsonUtils.jsonToList(json, TbItem.class); 71 return list; 72 }
三.展示购物车列表
/** * 展示购物车列表 * <p>Title: showCatList</p> * <p>Description: </p> * @param request * @return */ @RequestMapping("/cart/cart") public String showCatList(HttpServletRequest request, HttpServletResponse response) { //从cookie中取购物车列表 List<TbItem> cartList = getCartListFromCookie(request);//把列表传递给页面 request.setAttribute("cartList", cartList); //返回逻辑视图 return "cart"; }
四.更新购物车数量
/** * 更新购物车商品数量 */ @RequestMapping("/cart/update/num/{itemId}/{num}") @ResponseBody public E3Result updateCartNum(@PathVariable Long itemId, @PathVariable Integer num , HttpServletRequest request ,HttpServletResponse response) {//从cookie中取购物车列表 List<TbItem> cartList = getCartListFromCookie(request); //遍历商品列表找到对应的商品 for (TbItem tbItem : cartList) { if (tbItem.getId().longValue() == itemId) { //更新数量 tbItem.setNum(num); break; } } //把购物车列表写回cookie CookieUtils.setCookie(request, response, "cart", JsonUtils.objectToJson(cartList), COOKIE_CART_EXPIRE, true); //返回成功 return E3Result.ok(); }
》如果服务端返回406,大部分情况是没有导入jeckson的包,还有一种情况是请求的页面为html,因此浏览器希望得到的数据类型是html,但是响应的数据是其他数据类型,也会导致这个问题,一般解决方案是请求后缀改为action
五..删除购物车商品
/** * 删除购物车商品 */ @RequestMapping("/cart/delete/{itemId}") public String deleteCartItem(@PathVariable Long itemId, HttpServletRequest request, HttpServletResponse response) {//从cookie中取购物车列表 List<TbItem> cartList = getCartListFromCookie(request); //遍历列表,找到要删除的商品 for (TbItem tbItem : cartList) { if (tbItem.getId().longValue() == itemId) { //删除商品 cartList.remove(tbItem); //跳出循环 break; } } //把购物车列表写入cookie CookieUtils.setCookie(request, response, "cart", JsonUtils.objectToJson(cartList), COOKIE_CART_EXPIRE, true); //返回逻辑视图,重定向到显示购物车列表 return "redirect:/cart/cart.html"; } }
六.登录时使用购物车分析
七.用户登录拦截器实现
@Autowired private TokenService tokenService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 前处理,执行handler之前执行此方法。 //返回true,放行 false:拦截 //1.从cookie中取token String token = CookieUtils.getCookieValue(request, "token"); //2.如果没有token,未登录状态,直接放行 if (StringUtils.isBlank(token)) { return true; } //3.取到token,需要调用sso系统的服务,根据token取用户信息 E3Result e3Result = tokenService.getUserByToken(token); //4.没有取到用户信息。登录过期,直接放行。 if (e3Result.getStatus() != 200) { return true; } //5.取到用户信息。登录状态。 TbUser user = (TbUser) e3Result.getData(); //6.把用户信息放到request中。只需要在Controller中判断request中是否包含user信息。放行 request.setAttribute("user", user); return true; }
八.服务端添加单个商品-实现
》service层:
@Autowired private JedisClient jedisClient; @Value("${REDIS_CART_PRE}") private String REDIS_CART_PRE; @Autowired private TbItemMapper itemMapper; @Override public E3Result addCart(long userId, long itemId, int num) { //向redis中添加购物车。 //数据类型是hash key:用户id field:商品id value:商品信息 //判断商品是否存在 Boolean hexists = jedisClient.hexists(REDIS_CART_PRE + ":" + userId, itemId + ""); //如果存在数量相加 if (hexists) { String json = jedisClient.hget(REDIS_CART_PRE + ":" + userId, itemId + ""); //把json转换成TbItem TbItem item = JsonUtils.jsonToPojo(json, TbItem.class); item.setNum(item.getNum() + num); //写回redis jedisClient.hset(REDIS_CART_PRE + ":" + userId, itemId + "", JsonUtils.objectToJson(item)); return E3Result.ok(); } //如果不存在,根据商品id取商品信息 TbItem item = itemMapper.selectByPrimaryKey(itemId); //设置购物车数据量 item.setNum(num); //取一张图片 String image = item.getImage(); if (StringUtils.isNotBlank(image)) { item.setImage(image.split(",")[0]); } //添加到购物车列表 jedisClient.hset(REDIS_CART_PRE + ":" + userId, itemId + "", JsonUtils.objectToJson(item)); return E3Result.ok(); }
九.登录状态下-添加购物车
@RequestMapping("/cart/add/{itemId}") public String addCart(@PathVariable Long itemId, @RequestParam(defaultValue="1")Integer num, HttpServletRequest request, HttpServletResponse response) { //判断用户是否登录 TbUser user = (TbUser) request.getAttribute("user"); //如果是登录状态,把购物车写入redis if (user != null) { //保存到服务端 cartService.addCart(user.getId(), itemId, num); //返回逻辑视图 return "cartSuccess"; } //如果未登录使用cookie //从cookie中取购物车列表 List<TbItem> cartList = getCartListFromCookie(request); //判断商品在商品列表中是否存在 boolean flag = false; for (TbItem tbItem : cartList) { //如果存在数量相加 if (tbItem.getId() == itemId.longValue()) { flag = true; //找到商品,数量相加 tbItem.setNum(tbItem.getNum() + num); //跳出循环 break; } } //如果不存在 if (!flag) { //根据商品id查询商品信息。得到一个TbItem对象 TbItem tbItem = itemService.getItemById(itemId); //设置商品数量 tbItem.setNum(num); //取一张图片 String image = tbItem.getImage(); if (StringUtils.isNotBlank(image)) { tbItem.setImage(image.split(",")[0]); } //把商品添加到商品列表 cartList.add(tbItem); } //写入cookie CookieUtils.setCookie(request, response, "cart", JsonUtils.objectToJson(cartList), COOKIE_CART_EXPIRE, true); //返回添加成功页面 return "cartSuccess"; }
十.登录状态下-展示购物车列表-Service
@Override //合并cookie和redis的购物车
public E3Result mergeCart(long userId, List<TbItem> itemList) { //遍历商品列表 //把列表添加到购物车。 //判断购物车中是否有此商品 //如果有,数量相加 //如果没有添加新的商品 for (TbItem tbItem : itemList) { addCart(userId, tbItem.getId(), tbItem.getNum()); } //返回成功 return E3Result.ok(); } @Override //获取redis中的购物车列表数据 public List<TbItem> getCartList(long userId) { //根据用户id查询购车列表 List<String> jsonList = jedisClient.hvals(REDIS_CART_PRE + ":" + userId); List<TbItem> itemList = new ArrayList<>(); for (String string : jsonList) { //创建一个TbItem对象 TbItem item = JsonUtils.jsonToPojo(string, TbItem.class); //添加到列表 itemList.add(item); } return itemList; }
十一.登录状态下-展示购物车列表-表现层
/** * 展示购物车列表 * <p>Title: showCatList</p> * <p>Description: </p> * @param request * @return */ @RequestMapping("/cart/cart") public String showCatList(HttpServletRequest request, HttpServletResponse response) { //从cookie中取购物车列表 List<TbItem> cartList = getCartListFromCookie(request); //判断用户是否为登录状态 TbUser user = (TbUser) request.getAttribute("user"); //如果是登录状态 if (user != null) { //从cookie中取购物车列表 //如果不为空,把cookie中的购物车商品和服务端的购物车商品合并。 cartService.mergeCart(user.getId(), cartList); //把cookie中的购物车删除 CookieUtils.deleteCookie(request, response, "cart"); //从服务端取购物车列表 cartList = cartService.getCartList(user.getId()); } //把列表传递给页面 request.setAttribute("cartList", cartList); //返回逻辑视图 return "cart"; }
十二..登录状态下-修改、删除购物车
》service:
@Override public E3Result updateCartNum(long userId, long itemId, int num) { //从redis中取商品信息 String json = jedisClient.hget(REDIS_CART_PRE + ":" + userId, itemId + ""); //更新商品数量 TbItem tbItem = JsonUtils.jsonToPojo(json, TbItem.class); tbItem.setNum(num); //写入redis jedisClient.hset(REDIS_CART_PRE + ":" + userId, itemId + "", JsonUtils.objectToJson(tbItem)); return E3Result.ok(); } @Override public E3Result deleteCartItem(long userId, long itemId) { // 删除购物车商品 jedisClient.hdel(REDIS_CART_PRE + ":" + userId, itemId + ""); return E3Result.ok(); }
》controller:
/** * 更新购物车商品数量 */ @RequestMapping("/cart/update/num/{itemId}/{num}") @ResponseBody public E3Result updateCartNum(@PathVariable Long itemId, @PathVariable Integer num , HttpServletRequest request ,HttpServletResponse response) { //判断用户是否为登录状态 TbUser user = (TbUser) request.getAttribute("user"); if (user != null) { cartService.updateCartNum(user.getId(), itemId, num); return E3Result.ok(); } //从cookie中取购物车列表 List<TbItem> cartList = getCartListFromCookie(request); //遍历商品列表找到对应的商品 for (TbItem tbItem : cartList) { if (tbItem.getId().longValue() == itemId) { //更新数量 tbItem.setNum(num); break; } } //把购物车列表写回cookie CookieUtils.setCookie(request, response, "cart", JsonUtils.objectToJson(cartList), COOKIE_CART_EXPIRE, true); //返回成功 return E3Result.ok(); } /** * 删除购物车商品 */ @RequestMapping("/cart/delete/{itemId}") public String deleteCartItem(@PathVariable Long itemId, HttpServletRequest request, HttpServletResponse response) { //判断用户是否为登录状态 TbUser user = (TbUser) request.getAttribute("user"); if (user != null) { cartService.deleteCartItem(user.getId(), itemId); return "redirect:/cart/cart.html"; } //从cookie中取购物车列表 List<TbItem> cartList = getCartListFromCookie(request); //遍历列表,找到要删除的商品 for (TbItem tbItem : cartList) { if (tbItem.getId().longValue() == itemId) { //删除商品 cartList.remove(tbItem); //跳出循环 break; } } //把购物车列表写入cookie CookieUtils.setCookie(request, response, "cart", JsonUtils.objectToJson(cartList), COOKIE_CART_EXPIRE, true); //返回逻辑视图 return "redirect:/cart/cart.html"; }