品优购项目笔记(十三):购物车解决方案

    技术2022-07-12  75

    品优购项目笔记(十三)

    购物车业务购物车业务概要分析购物车对象封装分析购物车详细流程分析跨域访问问题购物车的controller方法购物车的service方法

    购物车业务

    购物车业务概要分析

    购物车对象封装分析

    购物车实体

    public class BuyerCart implements Serializable { private String sellerId;//商家ID private String sellerName;//商家名称 private List<OrderItem> orderItemList;//购物车明细 //..getset }

    购物项实体(在这里也是订单项)

    public class OrderItem implements Serializable { private Long id; /** * 商品id */ private Long itemId; /** * SPU_ID */ private Long goodsId; /** * 订单id */ private Long orderId; /** * 商品标题 */ private String title; /** * 商品单价 */ private BigDecimal price; /** * 商品购买数量 */ private Integer num; /** * 商品总金额 */ private BigDecimal totalFee; /** * 商品图片地址 */ private String picPath; private String sellerId; //...getset }

    购物车详细流程分析

    一、添加购物车 二、总体业务流程

    跨域访问问题

    当controller中的方法进行简单地完成之后,进行测试,发现点击加入购物车按钮没有反应 原因:跨域请求被阻止 什么是跨域请求: 浏览器厂商在开发浏览器时,设置了同源策略。 同源策略:要求发送请求的url地址和返回响应的url地址必须保证协议,ip地址,端口号不能够发生改变,只要有一个发生变化,浏览器就会认为这个响应不安全,会拒绝接收响应数据,这就是跨域请求访问。

    注意:如果前端window.location.href进行跳转,跳转到不同服务器页面,不会触发跨域访问问题,只是页面跳转,不会有数据返回

    解决方案

    jsonp:jquery如果发生ajax请求,可以将数据类型设置为jsonp,原理是jquery在发送数据的同时,会在数据中生产一个令牌,controller接收到数据后,进行处理,返回响应时,将令牌原样返回,jquery会判断令牌是否是当初发送的,如果是,则接收响应;反之,拒绝接收。cors:是w3c支持的解决方法,原理是在响应体设置信息Access-Control-Allow-Origin,如果使用SpringMVC4.2以上版本,可以使用@Cross注解,就相当于设置了响应头信息

    使用cors解决跨域问题

    /** * 添加商品到购物车 * @CrossOrigin注解,相当于设置了响应体信息,是w3c支持的一种跨域解决方案 * origins属性,设置的地址是返回响应给静态页面,静态页面所在服务器的地址 * @param itemId 商品库存id * @param num 购买数量 * @return */ @RequestMapping("/addGoodsToCartList") @CrossOrigin(origins = "http://localhost:8086", allowCredentials = "true") public Result addGoodsToCartList(Long itemId, Integer num){ return new Result(true,"添加成功!"); } //添加商品到购物车 $scope.addToCart=function(){ //alert('SKUID:'+$scope.sku.id ); $http.get('http://localhost:8080/cart/addGoodsToCartList.do?itemId=' +$scope.sku.id+'&num='+$scope.num ,{'withCredentials':true} ).success( function(response){ if(response.success){ location.href='http://localhost:8080/cart.html'; }else{ alert(response.message); } } ); }

    购物车的controller方法

    一、点击加入购物车按钮,将商品添加到购物车

    二、返回给前端购物车列表

    /** * 购物车业务 */ @RestController @RequestMapping("/cart") public class BuyerCartController { @Reference private CartService cartService; @Autowired private HttpServletRequest request; @Autowired private HttpServletResponse response; /** * 添加商品到购物车 * @CrossOrigin注解,相当于设置了响应体信息,是w3c支持的一种跨域解决方案 * origins属性,设置的地址是返回响应给静态页面,静态页面所在服务器的地址 * @param itemId 商品库存id * @param num 购买数量 * @return */ @RequestMapping("/addGoodsToCartList") @CrossOrigin(origins = "http://localhost:8086", allowCredentials = "true") public Result addGoodsToCartList(Long itemId, Integer num){ try { //1. 获取当前登录用户名称 String username = SecurityContextHolder.getContext().getAuthentication().getName(); //2. 获取购物车列表 List<BuyerCart> cartList = findCartList(); //3. 将当前商品加入到购物车列表 cartList = cartService.addItemToCartList(cartList,itemId,num); //4. 判断当前用户是否登录, 未登录用户名为"anonymousUser" if ("anonymousUser".equals(username)){ //4.a.如果未登录, 则将购物车列表存入cookie中 CookieUtil.setCookie(request, response, Constants.CART_LIST_COOKIE, JSON.toJSONString(cartList), 60 * 60 * 24 * 30, "utf-8"); //4.b.如果已登录, 则将购物车列表存入redis中 cartService.setCartListToRedis(username, cartList); } return new Result(true,"添加成功!"); } catch (Exception e) { e.printStackTrace(); return new Result(false, "添加失败!"); } } /** * 获取购物车列表数据 * @return */ @RequestMapping("/findCartList") public List<BuyerCart> findCartList(){ //1. 获取当前登录用户名称 String username = SecurityContextHolder.getContext().getAuthentication().getName(); //2. 从cookie中获取购物车列表json格式字符串 String cookieCartJson = CookieUtil.getCookieValue(request, Constants.CART_LIST_COOKIE, "utf-8"); //3. 如果购物车列表json串为空则返回"[]" if (cookieCartJson==null || "".equals(cookieCartJson)){ cookieCartJson = "[]"; } //4. 将购物车列表json转换为对象 List<BuyerCart> cookieCartList = JSON.parseArray(cookieCartJson, BuyerCart.class); //5. 判断用户是否登录, 未登录用户为"anonymousUser" if (!"anonymousUser".equals(username)){ //5.a. 未登录, 返回cookie中的购物车列表对象 return cookieCartList; }else { //5.b.1.已登录, 从redis中获取购物车列表对象 List<BuyerCart> redisCartList = cartService.getCartListToRedis(username); //5.b.2.判断cookie中是否存在购物车列表 if (cookieCartList.size()>0){ //如果cookie中存在购物车列表则和redis中的购物车列表合并成一个对象 cartService.mergeCookieCartListAndRedisCartList(cookieCartList,redisCartList); //删除cookie中购物车列表 CookieUtil.deleteCookie(request,response,Constants.CART_LIST_COOKIE); //将合并后的购物车列表存入redis中 cartService.setCartListToRedis(username,redisCartList); } //5.b.3.返回购物车列表对象 return redisCartList; } } }

    购物车的service方法

    package cn.itcast.core.service; import cn.itcast.core.dao.item.ItemDao; import cn.itcast.core.pojo.entity.BuyerCart; import cn.itcast.core.pojo.item.Item; import cn.itcast.core.pojo.order.OrderItem; import cn.itcast.core.util.Constants; import com.alibaba.dubbo.config.annotation.Service; 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; @Service public class CartServiceImpl implements CartService { @Autowired private ItemDao itemDao; @Autowired private RedisTemplate redisTemplate; @Override public List<BuyerCart> addItemToCartList(List<BuyerCart> cartList, Long itemId, Integer num) { //1. 根据商品SKU ID查询SKU商品信息 Item item = itemDao.selectByPrimaryKey(itemId); //2. 判断商品是否存在不存在, 抛异常 if (item == null){ throw new RuntimeException("该商品不存在!"); } //3. 判断商品状态是否为1已审核, 状态不对抛异常 if (!"1".equals(item.getStatus())){ throw new RuntimeException("该商品未审核!"); } //4.获取当前商品的商家ID String sellerId = item.getSellerId(); //5.根据商家ID查询购物车列表中是否存在该商家的购物车 BuyerCart buyerCart = findBuyerCartBySellerId(cartList, sellerId); //6.判断如果购物车列表中不存在该商家的购物车 if (buyerCart == null) { //6.a.1 新建购物车对象 buyerCart = new BuyerCart(); //设置新创建的购物车对象的卖家id buyerCart.setSellerId(sellerId); //设置新创建的购物车对象的卖家名称 buyerCart.setSellerName(item.getSeller()); //创建购物项集合 List<OrderItem> orderItemList = new ArrayList<>(); //创建购物项 OrderItem orderItem = createOrderItem(item, num); //将购物项添加到购物项集合 orderItemList.add(orderItem); //将购物项集合添加到购物车 buyerCart.setOrderItemList(orderItemList); //6.a.2 将新建的购物车对象添加到购物车列表 cartList.add(buyerCart); }else { //6.b.1如果购物车列表中存在该商家的购物车 (查询购物车明细列表中是否存在该商品) List<OrderItem> orderItemList = buyerCart.getOrderItemList(); OrderItem orderItem = findOrderItemByItemId(orderItemList, itemId); //6.b.2判断购物车明细是否为空 if (orderItem == null){ //6.b.3为空,新增购物车明细 orderItem= createOrderItem(item, num); //将新增购物项加入到购物项集合 orderItemList.add(orderItem); }else { //6.b.4不为空,在原购物车明细上添加数量,更改金额 orderItem.setNum(orderItem.getNum() + num); //设置总价格 orderItem.setTotalFee(orderItem.getPrice().multiply(new BigDecimal(orderItem.getNum()))); } //6.b.5如果购物车明细中数量操作后小于等于0,则移除 if (orderItem.getNum() <= 0){ orderItemList.remove(orderItem); } //6.b.6如果购物车中购物车明细列表为空,则移除 if (orderItemList.size() <= 0){ cartList.remove(buyerCart); } } //7. 返回购物车列表对象 return cartList; } /** * 判断当前购物项中是否存在这个商品 * @param orderItemList * @param itemId * @return */ private OrderItem findOrderItemByItemId(List<OrderItem> orderItemList, Long itemId){ if (orderItemList != null){ for (OrderItem orderItem : orderItemList) { if (orderItem.getItemId().equals(itemId)){ return orderItem; } } } return null; } /** * 创建购物项对象 * @param item * @param num * @return */ private OrderItem createOrderItem(Item item, Integer num){ if (num <= 0){ throw new RuntimeException("购买数量非法!"); } OrderItem orderItem = new OrderItem(); orderItem.setNum(num); orderItem.setGoodsId(item.getGoodsId()); orderItem.setItemId(item.getId()); orderItem.setPicPath(item.getImage()); orderItem.setPrice(item.getPrice()); orderItem.setSellerId(item.getSellerId()); orderItem.setTitle(item.getTitle()); orderItem.setTotalFee(item.getPrice().multiply(new BigDecimal(num))); return orderItem; } /** * 判断购物车中,是否有该商家的购物车 * @param cartList * @param sellerId * @return */ private BuyerCart findBuyerCartBySellerId(List<BuyerCart> cartList, String sellerId){ if (cartList != null){ for (BuyerCart buyerCart : cartList) { if (buyerCart.getSellerId().equals(sellerId)){ return buyerCart; } } } return null; } @Override public void setCartListToRedis(String username, List<BuyerCart> cartList) { redisTemplate.boundHashOps(Constants.CART_LIST_REDIS).put(username,cartList); } @Override public List<BuyerCart> getCartListToRedis(String username) { List<BuyerCart> cartList = (List<BuyerCart>)redisTemplate.boundHashOps(Constants.CART_LIST_REDIS).get(username); if (cartList == null){ cartList = new ArrayList<>(); } return cartList; } @Override public List<BuyerCart> mergeCookieCartListAndRedisCartList(List<BuyerCart> cookieCartList, List<BuyerCart> redisCartList) { if (cookieCartList != null){ //遍历cookie购物车集合 for (BuyerCart cookieCart : cookieCartList) { //遍历cookie购物车中的购物项集合 for (OrderItem cookieOrderItem : cookieCart.getOrderItemList()) { //将cookie中的购物项加入到redis的购物车集合中 redisCartList = addItemToCartList(redisCartList,cookieOrderItem.getItemId(),cookieOrderItem.getNum()); } } } return redisCartList; } }
    Processed: 0.013, SQL: 10