购物车列表的存储实现

需求分析

在这里插入图片描述
当我们点击加入购物车的时候,将商品加入到我们的购物车,页面传递到后台的信息是商品的id和数量,我们根据id和数量将商品放进购物车,购物车数据存储到cookie或者是服务器端
购物车列表在cookie的存储指的是我们在不登录的情况下也能将商品添加到购物车,这时购物车中的商品信息存储在浏览器端的cookie,用户清除浏览器缓存或者cookie过期后,购物车中就不存在商品信息
在这里插入图片描述
创建购物车的单个商家对象Cart,List Cart构成了购物车,Cart对象存储的是像京东自营、xx专卖店所包含商品的数据

public class Cart implements Serializable {

    private String sellerId;//商家id
    private String sellerName;//商家名称
    private List<TbOrderItem> orderItemList;//购物车明细

    public Cart() {
    }

    public Cart(String sellerId, String sellerName, List<TbOrderItem> orderItemList) {
        this.sellerId = sellerId;
        this.sellerName = sellerName;
        this.orderItemList = orderItemList;
    }

    public String getSellerId() {
        return sellerId;
    }

    public void setSellerId(String sellerId) {
        this.sellerId = sellerId;
    }

    public String getSellerName() {
        return sellerName;
    }

    public void setSellerName(String sellerName) {
        this.sellerName = sellerName;
    }

    public List<TbOrderItem> getOrderItemList() {
        return orderItemList;
    }

    public void setOrderItemList(List<TbOrderItem> orderItemList) {
        this.orderItemList = orderItemList;
    }
}

存储实现

注意
Long类型数据的比较通过longValue()方法在进行比较,而long类型可以通过==比较

/*
添加商品到购物车
cartList 老的购物车
 */
@Override
public List<Cart> addCart(List<Cart> cartList, Long itemId, Integer num) {
    TbItem item = itemMapper.selectByPrimaryKey(itemId);
    //做安全校验
    if (item==null){
        throw new RuntimeException("该商品不存在");
    }
    if (!item.getStatus().equals("1")){
        throw new RuntimeException("该商品暂不支持添加购物车");
    }
    String sellerId = item.getSellerId();
    Cart cart = searchItemInCartList(cartList, sellerId);
    if (cart!=null){//购物车中已经存在该商家
        List<TbOrderItem> orderItems = cart.getOrderItemList();//获取用户在这个商家中的商品明细
        //判断新商品在不在购物车的商品明细里
        TbOrderItem orderItem = searchItemInOrderOtemList(orderItems, itemId);
        if (orderItem!=null){//如果该商品已经在购物车中,改变数量和总价
            orderItem.setNum(orderItem.getNum()+num);
            orderItem.setTotalFee(new BigDecimal(orderItem.getPrice().doubleValue()*orderItem.getNum()));
            //移除商品数量减到0的商品明细
            if (orderItem.getNum()<=0){
                orderItems.remove(orderItem);
            }
            if (orderItems.size()==0){//如果商家在购物车列表的商品数量为0,就移除该商家
                cartList.remove(orderItems);
            }
        }
        else{//如果该商品不在购物车中,添加该商品信息到新建的商品明细中
            TbOrderItem newOrderItem = createOrderItem(item, num);
            orderItems.add(newOrderItem);
        }

    }
    else{//购物车中不存在该商家,创建该商家的购物明细
        TbOrderItem orderItem = createOrderItem(item, num);
        List<TbOrderItem> items = new ArrayList<>();//创建集合用来保存商品信息
        items.add(orderItem);
        Cart newCart = new Cart(item.getSellerId(),item.getSeller(),items);
        cartList.add(newCart);
    }
    return cartList;
}
/*
检测商家商品明细是否存在于购物车列表
 */
private Cart searchItemInCartList(List<Cart> cartList,String sellerId){
    for (Cart cart : cartList) {
        if (cart.getSellerId().equals(sellerId)) {//购物车中已经存在该商家
            return cart;
        }
    }
    return null;
}
/*
判断商品是否存在于商家商品明细中
 */
private TbOrderItem searchItemInOrderOtemList(List<TbOrderItem> itemList,Long itemId){
    for (TbOrderItem orderItem : itemList) {
        if (orderItem.getItemId().longValue()==itemId.longValue()) {//如果该商品已经在购物车中
            return orderItem;
        }
    }
    return null;
}
/*
新建商品明细中的单个商品信息
 */
private TbOrderItem createOrderItem(TbItem item,Integer num){
    TbOrderItem orderItem = new TbOrderItem();
    orderItem.setGoodsId(item.getGoodsId());
    orderItem.setItemId(item.getId());
    orderItem.setTitle(item.getTitle());
    orderItem.setNum(num);
    orderItem.setPrice(item.getPrice());
    orderItem.setTotalFee(new BigDecimal(orderItem.getPrice().doubleValue()*num));
    orderItem.setPicPath(item.getImage());
    return orderItem;
}

未登录保存在cookie中

在后端对cookie进行操作
注意
复杂对象是不能进行编码的,可以先转换成字符串,字符串是可编码的,这样就可以避免中文乱码

@Reference
private CartService cartService;

@Autowired
private HttpServletRequest request;

@Autowired
private HttpServletResponse response;
@RequestMapping("/add")
public Result addCart(Long itemId,Integer num){
    try {
        List<Cart> cartList = findCartList();
        List<Cart> carts = cartService.addCart(cartList, itemId, num);
        //存入cookie
        //复杂对象不支持编码,转成字符串,字符串是可编码的,防止对象中中文乱码
        String cartsJson = JSON.toJSONString(carts);
        CookieUtil.setCookie(request,response,"cartList",cartsJson,3600*24,"utf-8");
        return new Result(true,"加入购物车成功!");
    } catch (Exception e) {
        e.printStackTrace();
        return new Result(false,"加入购物车失败!");
    }

}

CookieUtil是我们自己封装的工具类

优化(登录存储在redis,未登录保存在cookie)

判断当前用户是否登陆,如果未登录采用Cookie存储,如果登录则采用Redis存储。登录后要进行Cookie购物车与Redis购物车的合并操作,并清除Cookie购物车。
修改spring-security.xml配置文件
之前我们是直接放行有关购物车操作的请求,这样的话spring-security就不会验证是否登录,也自然就没有登录相关信息
现在我们需要,spring-security里有登录相关信息,不登录也能执行有关购物车的操作,登录也可以操作
解决办法就是,修改拦截的权限
在这里插入图片描述
删除<http pattern="/cart/*.do" security="none"></http>
access=“IS_AUTHENTICATED_ANONYMOUSLY” 用于设置资源可以在不登陆时访问。
此配置与 security="none"的区别在于当用户未登陆时获取登陆人账号的值为anonymousUser,而security="none"的话,无论是否登陆都不能获取登录人账号的值。

否则:"/cart/*.do" security="none"表示不拦截,绕过spring security,此时SecurityContextHolder.getContext()上下文为空。

service层代码同上,修改controller代码如下

@Reference
private CartService cartService;

@Autowired
private HttpServletRequest request;

@Autowired
private HttpServletResponse response;

@Autowired
private RedisTemplate redisTemplate;
@RequestMapping("/addGoodsToCart")
public Result addCart(Long itemId,Integer num){

    try {
        List<Cart> cartList = findCartList();
        List<Cart> carts = cartService.addCart(cartList, itemId, num);
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        if ("anonymousUser".equals(username)){//没有登录,将信息存入cookie
            //存入cookie
            //复杂对象不支持编码,转成字符串,字符串是可编码的,防止对象中中文乱码
            String cartsJson = JSON.toJSONString(carts);
            CookieUtil.setCookie(request,response,"cartList",cartsJson,3600*24,"utf-8");
            System.out.println(">>>>>save cartList to cookie" );
        }
        else{//已登录,存入redis
            redisTemplate.boundHashOps("cartList").put(username,carts);
            System.out.println(">>>>>save cartList to Redis" );
        }

        return new Result(true,"加入购物车成功!");
    } catch (Exception e) {
        e.printStackTrace();
        return new Result(false,"加入购物车失败!");
    }

}
/*
获取到原来的购物车对象
 */
@RequestMapping("/findCartList")
public List<Cart> findCartList(){
    String username = SecurityContextHolder.getContext().getAuthentication().getName();
    if ("anonymousUser".equals(username)) {//没有登录,从cookie取出信息
        String cartListStr = CookieUtil.getCookieValue(request, "cartList","utf-8");
        if (cartListStr==null || cartListStr.equals("")){
            cartListStr = "[]";
        }
        List<Cart> cartList = JSON.parseArray(cartListStr, Cart.class);
        System.out.println(">>>>>get cartList from Cookie" );
        return cartList;
    }else{//已登录,从redis中取出信息
        List<Cart> cartList = (List<Cart>) redisTemplate.boundHashOps("cartList").get(username);
        if (cartList==null){
            cartList = new ArrayList<>();
        }
        System.out.println(">>>>>get cartList from Redis" );
        return cartList;
    }

}
@RequestMapping("/test")
public List<Cart> testCartList(){
    String cartListStr = CookieUtil.getCookieValue(request, "cartList","utf-8");
    if (cartListStr==null || cartListStr.equals("")){
        cartListStr = "[]";
    }
    List<Cart> cartList = JSON.parseArray(cartListStr, Cart.class);
    return cartList;
}

这样我们就做到了,未登录时,购物车信息存储在本地浏览器的cookie中,已登录时购物车信息存储在redis服务器中

购物车的合并(将cookie中的购物车信息同步到redis中)

service层新添合并方法,会调用之前的添加方法

/**
* 将cookieList合并到redisList
* @param redisList
* @param cookieList
* @return
*/
@Override
public List<Cart> joinCartList(List<Cart> redisList, List<Cart> cookieList) {
   for (Cart cart : cookieList) {
       List<TbOrderItem> orderItemList = cart.getOrderItemList();
       for (TbOrderItem orderItem : orderItemList) {
           addCart(redisList,orderItem.getItemId(),orderItem.getNum());
       }
   }
   return redisList;
}

修改controller层的获取方法

@RequestMapping("/findCartList")
public List<Cart> findCartList(){
    String username = SecurityContextHolder.getContext().getAuthentication().getName();
    // 从cookie中获取购物车列表,如果考虑将cookie同步到redis的情况
    // 那么,不管登录与否,都需要获取本地cookie数据
    String cartListStr = CookieUtil.getCookieValue(request, "cartList","utf-8");
    if (cartListStr==null || cartListStr.equals("")){
        cartListStr = "[]";
    }
    List<Cart> cookieList = JSON.parseArray(cartListStr, Cart.class);
    //没有登录,从cookie取出信息
    if ("anonymousUser".equals(username)) {
        System.out.println(">>>>>get cartList from Cookie" );
        return cookieList;
    }
    //已登录
    else{
        List<Cart> redisList = (List<Cart>) redisTemplate.boundHashOps("cartList").get(username);
        if (redisList==null){
            redisList = new ArrayList<>();
        }
        if (cookieList.size()>0){//如果cookie的购物车里有数据就进行合并,没有就直接返回redis中的数据
            //合并购物车
            redisList = cartService.joinCartList(redisList, cookieList);
            // 将合并后的数据重新存回redis
            redisTemplate.boundHashOps("cartList").put(username,redisList);
            // 合并完成后,删除本地的cookie
            CookieUtil.deleteCookie(request, response, "cartList");
            System.out.println(">>>>>import cookie to redis");
        }
        return redisList;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值