添加购物车:先拿到userid(登录则拿登陆了的,未登录检查cookie,cookie没有生成随机数),再把userid,skuid,num作为参数传到cartService.addCart(userId, skuId, num)。从购物车列表里面查数量。1、先去读缓存,如果缓存存在这个cartkey,则将ttl过期时间加10秒,不存在的话就通过userid拿到购物车列表,再用map保存(skuid,cartinfo)。再hmset(cartkey,map)。2、再看数据库,如果cart_info表已经有这个skuid,userid对应的信息,则是更新操作,cartInfoExists.setSkuNum(cartInfoExists.getSkuNum()+num);没有的话就是插入操作cartInfoMapper.insertSelective(cartInfo);3、最后将userid及对应的cartmap(skuid,cartInfo)加载到最新的缓存里面
controller
@PostMapping("addToCart") @LoginRequire(autoRedirect = false) public String addCart(@RequestParam("skuId") String skuId, @RequestParam("num") int num, HttpServletRequest request, HttpServletResponse response){ String userId =(String) request.getAttribute("userId"); if(userId==null){ //如果用户未登录 检查cookie用户是否有token 如果有token 用token 作为id 加购物车 如果没有生成一个新的token放入cookie userId = CookieUtil.getCookieValue(request, "user_tmp_id", false); if(userId==null){ userId = UUID.randomUUID().toString(); CookieUtil.setCookie(request,response,"user_tmp_id",userId,60*60*24*7,false); } } CartInfo cartInfo = cartService.addCart(userId, skuId, num);//实例化,参数 //userid用户名,skuId订单名,num数量 request.setAttribute("cartInfo",cartInfo); request.setAttribute("num",num); return "success"; }
service
@Override public CartInfo addCart(String userId, String skuId, Integer num) { // 为了防止 更新购物车前 缓存过期 loadCartCacheIfNotExists( userId) ; // 加数据库 // 尝试取出已有的数据 CartInfo cartInfoQuery=new CartInfo(); cartInfoQuery.setSkuId(skuId); cartInfoQuery.setUserId(userId); CartInfo cartInfoExists=null; cartInfoExists = cartInfoMapper.selectOne(cartInfoQuery); SkuInfo skuInfo = manageService.getSkuInfo(skuId); if(cartInfoExists!=null){//如果有 把数量更新 update cartInfoExists.setSkuName(skuInfo.getSkuName()); cartInfoExists.setCartPrice(skuInfo.getPrice()); cartInfoExists.setSkuNum(cartInfoExists.getSkuNum()+num); cartInfoExists.setImgUrl(skuInfo.getSkuDefaultImg()); cartInfoMapper.updateByPrimaryKeySelective(cartInfoExists); }else{// 如果没有insert CartInfo cartInfo = new CartInfo(); cartInfo.setSkuId(skuId); cartInfo.setUserId(userId); cartInfo.setSkuNum(num); cartInfo.setImgUrl(skuInfo.getSkuDefaultImg()); cartInfo.setSkuName(skuInfo.getSkuName()); cartInfo.setCartPrice(skuInfo.getPrice()); cartInfo.setSkuPrice(skuInfo.getPrice()); cartInfoMapper.insertSelective(cartInfo); cartInfoExists=cartInfo; } loadCartCache(userId); return cartInfoExists; }
缓存数据库一致性操作
public void loadCartCacheIfNotExists(String userId){//缓存数据库的一致性 String cartkey="cart:"+userId+":info"; Jedis jedis = redisUtil.getJedis(); Long ttl = jedis.ttl(cartkey); int ttlInt = ttl.intValue(); jedis.expire(cartkey,ttlInt+10); Boolean exists = jedis.exists(cartkey); jedis.close(); if( !exists){//缓存没有的情况 loadCartCache( userId);//查数据库,同时加载到缓存里面 } }
* 缓存没有的情况下,查数据库 ,同时加载到缓存中 ```java /** * 缓存没有查数据库 ,同时加载到缓存中 * @param userId * @return */ public List<CartInfo> loadCartCache(String userId){ // 读取数据库 List<CartInfo> cartInfoList = cartInfoMapper.selectCartListWithSkuPrice(userId); //加载到缓存中 //为了方便插入redis 把list --> map if(cartInfoList!=null&&cartInfoList.size()>0) { Map<String, String> cartMap = new HashMap<>(); for (CartInfo cartInfo : cartInfoList) { cartMap.put(cartInfo.getSkuId(), JSON.toJSONString(cartInfo)); } Jedis jedis = redisUtil.getJedis(); String cartKey = "cart:" + userId + ":info"; jedis.del(cartKey); jedis.hmset(cartKey, cartMap); // hash jedis.expire(cartKey, 60 * 60 * 24); jedis.close(); } return cartInfoList; }
购物车列表:有登陆,登录之前存在临时id,则进行合并,不需要的话则直接拿到userid的购物车列表。未登录的话直接拿到临时id的购物车列表。查询购物车列表的操作是先取缓存,拿到cartInfoJsonList,命中缓存后将遍历通过cartJson拿到cartInfo,加入cartList。并通过id的大小倒叙返回。如果缓存中没拿到,先查询数据库拿到userid对应的所有的cartInfoList,再将将其包装为map(skuid,cartInfo),其加载到缓存中String cartKey = "cart:" + userId + ":info"; jedis.hmset(cartKey, cartMap);。
controller
@GetMapping("cartList") @LoginRequire(autoRedirect = false) public String cartList(HttpServletRequest request){ String userId =(String) request.getAttribute("userId"); //查看用户登录id if(userId!=null){ //有登录 List<CartInfo> cartList=null; //如果登录前(未登录)时,存在临时购物车 ,要考虑合并 String userTmpId=CookieUtil.getCookieValue(request, "user_tmp_id", false); //取临时id if(userTmpId!=null){ List<CartInfo> cartTempList = cartService.cartList( userTmpId); //如果有临时id ,查是否有临时购物车 if( cartTempList!=null&&cartTempList.size()>0){ cartList= cartService.mergeCartList(userId,userTmpId); // 如果有临时购物车 ,那么进行合并 ,并且获得合并后的购物车列表 } } if(cartList==null||cartList.size()==0){ cartList = cartService.cartList( userId); //如果不需要合并 ,再取登录后的购物车 } request.setAttribute("cartList",cartList); }else { //未登录 直接取临时购物车 String userTmpId=CookieUtil.getCookieValue(request, "user_tmp_id", false); if(userTmpId!=null) { List<CartInfo> cartTempList = cartService.cartList(userTmpId); request.setAttribute("cartList",cartTempList); } } return "cartList"; }
service
@Override public List<CartInfo> cartList(String userId) { //先查缓存 Jedis jedis = redisUtil.getJedis(); String cartKey="cart:"+userId+":info"; List<String> cartJsonList = jedis.hvals(cartKey);//取缓存 List<CartInfo> cartList=new ArrayList<>(); if(cartJsonList!=null&&cartJsonList.size()>0){ //缓存命中 for (String cartJson : cartJsonList) { CartInfo cartInfo = JSON.parseObject(cartJson, CartInfo.class); cartList.add(cartInfo); } cartList.sort(new Comparator<CartInfo>() {//根据时间排序(id的一个倒叙排序) @Override public int compare(CartInfo o1, CartInfo o2) { return o2.getId().compareTo(o1.getId()); } }); return cartList; }else { //缓存未命中 return loadCartCache(userId);//先查数据库 ,再加载到缓存中 } }
/** * 合并购物车 * @param userIdDest * @param userIdOrig * @return */ @Override public List<CartInfo> mergeCartList(String userIdDest, String userIdOrig) { //1 先做合并 cartInfoMapper.mergeCartList(userIdDest,userIdOrig);//数据库 // 2 合并后把临时购物车删除 CartInfo cartInfo = new CartInfo(); cartInfo.setUserId(userIdOrig); cartInfoMapper.delete(cartInfo); Jedis jedis = redisUtil.getJedis(); jedis.del("cart:"+userIdOrig+":info"); jedis.close(); // 3 重新读取数据 加载缓存 List<CartInfo> cartInfoList = loadCartCache(userIdDest); return cartInfoList; }
购物车列表的选中
controller
@PostMapping("checkCart") @LoginRequire(autoRedirect = false) @ResponseBody public void checkCart(@RequestParam("isChecked") String isChecked ,@RequestParam("skuId") String skuId,HttpServletRequest request){ String userId =(String)request.getAttribute("userId"); if(userId==null){ userId = CookieUtil.getCookieValue(request, "user_tmp_id", false); } cartService.checkCart(userId,skuId,isChecked); }
service
@Override public void checkCart(String userId, String skuId, String isChecked) { loadCartCacheIfNotExists(userId);// 检查一下缓存是否存在 避免因为缓存失效造成 缓存和数据库不一致 // isCheck数据 值保存在缓存中 //保存标志 String cartKey = "cart:" + userId + ":info"; Jedis jedis = redisUtil.getJedis(); String cartInfoJson = jedis.hget(cartKey, skuId); CartInfo cartInfo = JSON.parseObject(cartInfoJson, CartInfo.class); cartInfo.setIsChecked(isChecked); String cartInfoJsonNew = JSON.toJSONString(cartInfo); jedis.hset(cartKey,skuId,cartInfoJsonNew); // 为了订单结账 把所有勾中的商品单独 在存放到一个checked购物车中 String cartCheckedKey = "cart:" + userId + ":checked"; if(isChecked.equals("1")){ //勾中加入到待结账购物车中, 取消勾中从待结账购物车中删除 jedis.hset(cartCheckedKey,skuId,cartInfoJsonNew); jedis.expire(cartCheckedKey,60*60); }else{ jedis.hdel(cartCheckedKey,skuId); } jedis.close(); }