购物车实现(cookie+redis)

购物车实现(cookie+redis)

用户未登录, 添加商品到购物车时, 将购物车信息存储到cookie中

用户登录后,将cookie中的购物车合并到redis中,删除cookie信息,添加商品时,直接添加到redis中

1.controller

@Autowired
private HttpServletResponse response;

controller中可以直接autowired response request

不会发生线程安全问题, spring框架已经处理好了

package com.pyg.cart.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.pyg.cart.service.CartService;
import com.pyg.pojogroup.Cart;
import com.pyg.util.CookieUtil;
import entity.Result;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
 * @Title: CartController
 * @ProjectName PYG
 * @Description: TODO
 */
@RestController
@RequestMapping("/cart")
public class CartController {

    @Reference
    private CartService cartService;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private HttpServletResponse response;

    /**
     * @Description: 添加商品到购物车 cookie
     * @param itemId
     * @param num
     * @return entity.Result
     */
    @RequestMapping("/addGoodsToCartList")
    //解决js跨域问题 origins 允许访问这个controller的请求地址 
    //allowCredentials 默认为true  请求中携带着cookie来时,必须为true
    @CrossOrigin(origins = "http://localhost:9105",allowCredentials="true")
    public Result addGoodsToCartList(Long itemId, Integer num){
        try{
            //Security获取用户名
            String username = SecurityContextHolder.getContext().getAuthentication().getName();
            //获得购物车列表
            List<Cart> cartList = findCartList();
            //调用service更新购物车
            cartList=cartService.addGoodsToCartList(cartList,itemId,num);
            if("anonymousUser".equals(username)){
                //未登录 将更新后的购物车写回cookie
                String cartListStr = JSON.toJSONString(cartList);
                CookieUtil.setCookie(request,response,"cartList",cartListStr,3600*24,"utf-8");
            }else{
                //登录 写回到redis
                cartService.saveCartListToRedis(cartList,username);
            }
            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();
        String cartListCookie = CookieUtil.getCookieValue(request, "cartList", "utf-8");
        if(StringUtils.isEmpty(cartListCookie)){
            cartListCookie="[]";
        }
        List<Cart> cookie_cartList = JSON.parseArray(cartListCookie, Cart.class);
        if("anonymousUser".equals(username)){
            //未登录 cookie中取出购物车数据
            return  cookie_cartList;
        }else{
            //登录状态 从redis取出购物车
            List<Cart> redis_cartList=cartService.findCartListFromRedis(username);
            //合并购物车
            if(cookie_cartList!=null && cookie_cartList.size()>0){
                redis_cartList=cartService.mergeCartList(redis_cartList,cookie_cartList);
                cartService.saveCartListToRedis(redis_cartList,username);
                //删除cookie中的购物车
                CookieUtil.deleteCookie(request,response,"cartList");
            }
            return redis_cartList;
        }
    }

}

2.service
package com.pyg.cart.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.pyg.cart.service.CartService;
import com.pyg.mapper.TbItemMapper;
import com.pyg.pojo.TbItem;
import com.pyg.pojo.TbOrderItem;
import com.pyg.pojogroup.Cart;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @Title: CartServiceImpl
 * @ProjectName PYG
 * @Description: TODO
 */

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private TbItemMapper itemMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * @param cartList
     * @param itemId
     * @param num
     * @return java.util.List<com.pyg.pojogroup.Cart>
     * @Description: 添加商品到购物车
     */
    @Override
    public List<Cart> addGoodsToCartList(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("商品状态无效");
        }

        Cart cart = searchCartBySellerId(cartList, item.getSellerId());

        //商家不存在
        if(cart==null){
            cart = new Cart();
            cart.setSellerId(item.getSellerId());
            cart.setSellerName(item.getSeller());

            List<TbOrderItem> orderItemList = new ArrayList<>();
            orderItemList.add(createOrderItem(item,num));
            cart.setOrderItemList(orderItemList);
            cartList.add(cart);
        }else{
            //商家存在
            TbOrderItem orderItem = searchOrderItemByItemId(cart.getOrderItemList(), itemId);
            if(orderItem==null){
                //该商品不在列表中
                TbOrderItem orderItem1 = createOrderItem(item, num);
                cart.getOrderItemList().add(orderItem1);
            }else{
                orderItem.setNum(orderItem.getNum()+num);
                orderItem.setTotalFee(new BigDecimal(orderItem.getNum()*orderItem.getPrice().doubleValue()));

                if(orderItem.getNum()<=0){
                    cart.getOrderItemList().remove(orderItem);
                }
                if(cart.getOrderItemList().size()<=0){
                    cartList.remove(cart);
                }
            }

        }
        return cartList;
    }


    /**
     * @Description: 判断商家是否在购物车中
     * @param cartList
     * @param sellerId
     * @return com.pyg.pojogroup.Cart
     */
    private Cart searchCartBySellerId(List<Cart> cartList,String sellerId){
        for (Cart cart : cartList) {
            if(cart.getSellerId().equals(sellerId)){
                return cart;
            }
        }
        return null;
    }
    
    /**
     * @Description: 判断商品是否在购物车对应的商家商品列表中
     * @param orderItemList
     * @param itemId
     * @return com.pyg.pojo.TbOrderItem
     */
    private TbOrderItem searchOrderItemByItemId(List<TbOrderItem> orderItemList,Long itemId){
        for (TbOrderItem orderItem : orderItemList) {
            if(orderItem.getItemId().longValue()==itemId.longValue()){
                return orderItem;
            }
        }
        return null;
    }
    
    /**
     * @Description: 创建一个OrderItem存入购物车对应的商家商品列表中
     * @param item
     * @param num
     * @return com.pyg.pojo.TbOrderItem
     */
    private TbOrderItem createOrderItem(TbItem item,Integer num){
        if(num<=0){
            throw new RuntimeException("数量非法!");
        }
        TbOrderItem tbOrderItem=new TbOrderItem();
        tbOrderItem.setItemId(item.getId());
        tbOrderItem.setGoodsId(item.getGoodsId());
        tbOrderItem.setTitle(item.getTitle());
        tbOrderItem.setPrice(item.getPrice());
        tbOrderItem.setNum(num);
        tbOrderItem.setTotalFee(new BigDecimal(tbOrderItem.getNum()*tbOrderItem.getPrice().doubleValue()));
        tbOrderItem.setPicPath(item.getImage());
        tbOrderItem.setSellerId(item.getSellerId());
        return tbOrderItem;
    }

	/**
     * @Description: 从redis中查找对应用户的购物车信息
     * @param username
     * @return java.util.List<com.pyg.pojogroup.Cart>
     */
    @Override
    public List<Cart> findCartListFromRedis(String username) {
        Object obj = redisTemplate.boundHashOps("cartList").get(username);
        if(obj==null){
            return new ArrayList<>();
        }
        return (List<Cart>) obj;
    }
	/**
     * @Description: 保存购物车信息到redis中
     * @param cartList
     * @param username
     * @return void
     */
    @Override
    public void saveCartListToRedis(List<Cart> cartList, String username) {
        redisTemplate.boundHashOps("cartList").put(username,cartList);
    }
	/**
     * @Description: 合并cookie和redis购物车
     * @param redis_cartList
     * @param cookie_cartList
     * @return java.util.List<com.pyg.pojogroup.Cart>
     */
    @Override
    public List<Cart> mergeCartList(List<Cart> redis_cartList, List<Cart> cookie_cartList) {
        for (Cart cart : cookie_cartList) {
            for (TbOrderItem tbOrderItem : cart.getOrderItemList()) {
                redis_cartList = addGoodsToCartList(redis_cartList, tbOrderItem.getItemId(), tbOrderItem.getNum());
            }
        }
        return redis_cartList;
    }
}

3.springsecurity.xml 小问题

access=“IS_AUTHENTICATED_ANONYMOUSLY” 用于设置资源可以在不登陆时可以访问。

拦截了但是给了一个默认的权限

SecurityContextHolder.getContext().getAuthentication().getName(); 用户名为anonymousUser

此配置与 security="none"的区别在于当用户未登陆时获取登陆人账号的值为anonymousUser ,

而security="none"的话,无论是否登陆都不能获取登录人账号的值,因为springsecutiry压根没拦截cart.do 不存在上下文 所以getName时是null。

<!-- 匿名访问资源 -->
    <http pattern="/css/**" security="none"></http>
    <http pattern="/js/**" security="none"></http>
    <http pattern="/img/**" security="none"></http>
    <http pattern="/plugins/**" security="none"></http>
    <http pattern="/cart.html" security="none"></http>

    <!---->
    <http use-expressions="false" entry-point-ref="casProcessingFilterEntryPoint">
        <intercept-url pattern="/cart/*.do" access="IS_AUTHENTICATED_ANONYMOUSLY"></intercept-url>
        <intercept-url pattern="/**" access="ROLE_USER"/>
        <csrf disabled="true"/>
        
        <custom-filter ref="casAuthenticationFilter" position="CAS_FILTER"/>
        <custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
        <custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
    </http>
  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值