电商之购物车的实现

 public class CartInfo实现Serializable {@GeneratedValue(strategy = GenerationType.IDENTITY)@Id @Column String id; @Column //用户Id String userId; @Column //商品唯一Id标识String skuId; @Column //购物车价格可能与商品当前的真实价格不一致,BigDecimal cartPrice; @Column //商品数量Integer skuNum; @Column String imgUrl; @Column //商品名称String skuName; //实时价格@Transient BigDecimal skuPrice; //下订单的时候,商品是否勾选@Transient String isChecked =“0”; }``2 Redis缓存中存放的数据结构分析因为购物车信息会频繁增加改,而且可能频繁修改某个商品,因此不适合用于数据类型存储。应该使用redis中的hash结构存储。这样就可以键:“用户:用户id]:购物车”字段:[skuId]值:CartInfo(JSON)其中用户:是键前缀:购物车是钥匙后缀skuId是商品的唯一ID标识CartInfoJosn是具体的商品购物车信息









































##三具体实现流程及思路##从添加到购物车,一个这页面按钮开始实现页面加入购物车这一按按会提交一个表单数据到后台,这个表单数据应该是{“skuNum”:“。 “”skuId“:”“}这样的JSON数据而且要考虑两种情况1.用户已经登陆,直接插入数据库,并在缓存中存一份,但是要考虑用户的购物车中是否原来已经有这件商品了,原来就有,改个数量即可,原来没有则需要新插入一条数据2.用户还没有登陆,可以将购物车信息暂存在饼干中,用户当登陆后与数据库中的数据进行合并所以我们的控制器“/ addToCart”应该是这样的。``` @RequestMapping(“addToCart”)//设置是否需要登陆才能访问这里设置为假指不必登陆具体实现在上一篇分布式架构的单点登录中有详细代码@LoginRequire(autoRedirect = false)public String addCart(String skuId,Integer skuNum,HttpServletReque st requ est,HttpServletResponse response){





































    String USER_KEY_PREFIX =“user:”; String USER_CART_KEY_SUFFIX =“:cart”; 字符串USER_CHECKED_KEY_SUFFIX =“:已检查”; 字符串USERINFOKEY_SUFFIX =“:info”; } @覆盖公共CartInfo addToCart(字符串skuId,字符串userid,整型skuNum){//根据用户标识和skuId去数据库中查询当前用户的购物车信息CartInfo cartInfo = new CartInfo(); cartInfo.setSkuId(skuId); cartInfo.setUserId(用户ID); //返回null说明用户还有将这个商品添加到购物车,若有返回值,说明用户的购物车里已经有了这个商品CartInfo cartInfoExist = cartInfoMapper.selectOne(cartInfo); if(cartInfoExist!= null){//更新数量cartInfoExist.setSkuNum(cartInfoExist.cartInfoMapper.updateByPrimaryKeySelective(cartInfoExist); } else {//用户刚买的商品往购物车中添加//先查询出这个商品的详细信息SkuInfo skuInfo = managerService.getSkuInfo(skuId); //将查询出的商品详细信息设置到购物车商品中cartInfo.setCartPrice(skuInfo.getPrice()); cartInfo.setSkuPrice(skuInfo.getPrice()); cartInfo.setSkuName(skuInfo.getSkuName());




























         cartInfo.setImgUrl(skuInfo.getSkuDefaultImg()); 
         cartInfo.setSkuNum(skuNum); 
         cartInfoMapper.insertSelective(cartInfo); 
         cartInfoExist = cartInfo; 
     } 
     //最后放入到redis中
     字符串userCartKey = CartConst.USER_KEY_PREFIX + userId + CartConst.USER_CART_KEY_SUFFIX; 
     Jedis jedis = redisUtil.getJedis(); 
     jedis.hset(userCartKey,skuId,JSON.toJSONString(cartInfoExist)); 
     //更新redis缓存过期时间
     String userInfoKey = CartConst.USER_KEY_PREFIX + userId + CartConst.USERINFOKEY_SUFFIX; 
     Long ttl = jedis.ttl(userInfoKey); 
     jedis.expire(userCartKey,ttl.intValue()); 
     jedis.close(); 
     return cartInfoExist;
} ```
 CartCookieHandler中将购物车信息保存到cookie的方法:``` //定义购物车cookie名称private final String cookieCartName =“CART”; // cookie过期时间private final int COOKIE _ CART _ MAXAGE = 7 * 24 * 3600; //未登录的时候,添加到购物车实现思路和登陆时基本一致也是判断是增加数量还是添加新的数据public void addToCart(HttpServletRequest request,HttpServletResponse response,String skuId,String userId,Integer skuNum){//从饼干中查到购物车商品信息CookieUtil是一个工具类用于设置和获取的cookie中的值String cartJson = CookieUtil.getCookieValue(request,cookieCartName,true); 列表<CartInfo>










cartInfoList = new ArrayList <>(); boolean ifExist = false; if(cartJson!= null){cartInfoList = JSON.parseArray(cartJson,CartInfo.class); for(CartInfo cartInfo:cartInfoList){//判断是增加数量还是新添加一个商品if(cartInfo.getSkuId()。equals(skuId)){cartInfo.setSkuNum(cartInfo.getSkuNum()+ skuNum); ifExist = true; 打破; 如果(ifExist!){SkuInfo skuInfo = manageService.getSkuInfo(skuId); CartInfo cartInfo = new CartInfo(); cartInfo.setSkuId(skuId); cartInfo.setCartPrice(skuInfo.getPrice()); cartInfo.setSkuPrice(skuInfo.getPrice()); cartInfo.setSkuName(skuInfo.getSkuName()); cartInfo.setImgUrl(skuInfo.getSkuDefaultImg()); cartInfo.setUserId(用户ID); cartInfo.setSkuNum(skuNum); cartInfoList.add(cartInfo); }         字符串newCartJson = JSON.toJSONString(cartInfoList);




























        CookieUtil.setCookie(请求,响应cookieCartName,newCartJson,COOKIE_CART_MAXAGE,TRUE); 
    } ```
就进入了这样的页面![这里写图片描述

](https://img-blog.csdn.net/20180814211650783?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTcwMjg3Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
然后在这个页面点击去购物车结算查询出当前用户所有的购物车商品列表显示
这里也分为两种情况,登陆时从数据库和缓存中查,未登陆从cookie中查
相应的控制代码如下:
@RequestMapping("/cartList")
@LoginRequire(autoRedirect = false)
public String cartList(HttpServletRequest request,HttpServletResponse response){ 
    //判断用户是否登录了登陆了就从redis中获取并判断是否要合并购物车
    //没有登陆就从cookie中
    String userId =(String)request.getAttribute(“userId”); if(userId!= null){//可能用户刚刚登陆cookie中还有部分数据List <CartInfo> cartListFromCookie = cartCookieHandler.getCartList(request); List <CartInfo> cartList = null; // cookie中有数据if(cartListFromCookie!= null && cartListFromCookie.size()> 0){//开始合并并存到redis和数据库中cartService.mergeToCartList(cartListFromCookie,用户id);                 cartCookieHandler.deleteCartCookie(请求,响应);             }             //最后再从redis中取得,或者从数据库中取得所有的购物车数据            cartList = cartService.getCartList(userId);             //设置到请求域中            了了了request.setAttribute(“cartList”,cartList);         } else { 

“` 公开名单

getCartList(HttpServletRequest的请求){
String cookieValue = CookieUtil.getCookieValue(request,cookieCartName,true); List < CartInfo > cartInfoList = JSON.parseArray(cookieValue,CartInfo.class); return cartInfoList; } @覆盖 公共列表< CartInfo > mergeToCartList(列表< CartInfo > cartListFromCookie,字符串userid){ //从数据库中根据用户id查询到所有数据库中的购物车信息 列表< CartInfo >

cartInfoListDB = cartInfoMapper.selectCartListWithCurPrice(userId); if(cartInfoListDB!= null && cartInfoListDB.size()> 0){//循环cookie中的数据for(CartInfo cartInfoCk:cartListFromCookie){boolean isMatch = false; //循环DB中的数据cartInfoListDB for(CartInfo cartInfoDB:cartInfoListDB){if(cartInfoDB.getSkuId()。equals(cartInfoCk.getSkuId())){//更新到数据库cartInfoDB.setSkuNum(cartInfoCk.getSkuNum()+ cartInfoDB .getSkuNum()); cartInfoMapper.updateByPrimaryKeySelective(cartInfoDB); isMatch = true; 打破; }

            } 
            //数据库中还没有这件商品
            ,如果(isMatch!){ 
                cartInfoCk.setUserId(用户ID); 
                cartInfoMapper.insertSelective(cartInfoCk); 
            } 
        } 
    }否则{ 
        对于(CartInfo cartInfo:cartListFromCookie){ 
            cartInfoMapper.insertSelective(cartInfo); 
        } 
    } 
    //从数据库根据用户ID购物查询车信息并放到缓存中保证数据库与缓存中数据的harmony和谐
    列表<CartInfo> cartInfoList = loadCartCache(用户ID); //更新缓存中该商品的勾选状态后边会讲购物车中的商品勾选状态//如果这里不进行更改,会发生本来未登录时用户对购物车商品的勾选状态在登陆后丢失了这个勾选的状态        为(CartInfo cartInfoDB:cartInfoList){             for(CartInfo cartInfoCk:cartListFromCookie){





            if(cartInfoCk.getSkuId().equals(cartInfoDB.getSkuId())){
                if(“1”.equals(cartInfoCk.getIsChecked())){ 
                    cartInfoDB.setIsChecked(cartInfoCk.getIsChecked()); 
                    checkCart(cartInfoDB.getSkuId(),cartInfoCk.getIsChecked(),用户id); 
                } 
            } 
        } 
    } 
    返回cartInfoList; 
} 

//从数据库根据用户id查询购物车信息并放到缓存中私人列表 loadCartCache(字符串userid){列表 cartInfoList = cartInfoMapper.selectCartListWithCurPrice(用户id);

    Jedis jedis = redisUtil.getJedis(); String userCartKey = CartConst.USER _ KEY _ PREFIX + userId + CartConst.USER _ CART _ KEY_SUFFIX; if(cartInfoList!= null && cartInfoList.size()> 0){//放到缓存中Map <String,String> map = new HashMap <>(); for(CartInfo cartInfo:cartInfoList){map.put(cartInfo.getSkuId(),JSON.toJSONString(cartInfo)); jedis.hmset(userCartKey,地图); } else {jedis.close(); return null; } //更新过期时间String userInfoKey = CartConst.USER_KEY_PREFIX + userId + CartConst.USERINFOKEY_SUFFIX; Long ttl = jedis.ttl(userInfoKey); jedis.expire(userCartKey,ttl.intValue()); jedis.close(); return cartInfoList;

https://img-blog.csdn.net/20180815123637428?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTcwMjg3Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70 )“` <! - 这是复选框的按钮复选框页面使用了thymeleaf所以有th:value - >

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值