Loading

购物车

购物车分为用户登录购物车和未登录购物车操作,国内知名电商京东用户登录和不登录都可以操作购物车,如果用户不登录,操作购物车可以将数据存储到Cookie,用户登录后购物车数据可以存储到Redis中,再将之前未登录加入的购物车合并到Redis中即可。

淘宝天猫则采用了另外一种实现方案,用户要想将商品加入购物车,必须先登录才能操作购物车。

我们今天实现的购物车是天猫解决方案,即用户必须先登录才能使用购物车功能。

购物车业务分析

(1)需求分析

用户在商品详细页点击加入购物车,提交商品SKU编号和购买数量,添加到购物车。购物车展示页面如下:

(2)购物车实现思路

我们实现的是用户登录后的购物车,用户将商品加入购物车的时候,直接将要加入购物车的详情存入到Redis即可。每次查看购物车的时候直接从Redis中获取。

(3)表结构分析

用户登录后将商品加入购物车,需要存储商品详情以及购买数量,购物车详情表如下:

changgou_order数据中tb_order_item表:

CREATE TABLE `tb_order_item` (
  `id` varchar(20) COLLATE utf8_bin NOT NULL COMMENT 'ID',
  `category_id1` int(11) DEFAULT NULL COMMENT '1级分类',
  `category_id2` int(11) DEFAULT NULL COMMENT '2级分类',
  `category_id3` int(11) DEFAULT NULL COMMENT '3级分类',
  `spu_id` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT 'SPU_ID',
  `sku_id` bigint(20) NOT NULL COMMENT 'SKU_ID',
  `order_id` bigint(20) NOT NULL COMMENT '订单ID',
  `name` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '商品名称',
  `price` int(20) DEFAULT NULL COMMENT '单价',
  `num` int(10) DEFAULT NULL COMMENT '数量',
  `money` int(20) DEFAULT NULL COMMENT '总金额',
  `pay_money` int(11) DEFAULT NULL COMMENT '实付金额',
  `image` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '图片地址',
  `weight` int(11) DEFAULT NULL COMMENT '重量',
  `post_fee` int(11) DEFAULT NULL COMMENT '运费',
  `is_return` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '是否退货',
  PRIMARY KEY (`id`),
  KEY `item_id` (`sku_id`),
  KEY `order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

添加购物车

获取sku数据

goods服务中定义根据id查询sku对象实现

@RestController
@CrossOrigin
@RequestMapping("/sku")
public class SkuController {
​
​
    @Autowired
    private SkuService skuService;
​
     @GetMapping("/{id}")
    public Result<Sku> findById(@PathVariable("id") String id){
        Sku sku = skuService.findById(id);
        return new Result(true,StatusCode.OK,"查询成功",sku);
    }
}

定义feign接口

goods-api工程中定义skuFeign接口,并定义查询方法

 /**
     * 根据id查询sku信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result<Sku> findById(@PathVariable("id") String id);

订单服务添加依赖

<dependency>
    <groupId>com.changgou</groupId>
    <artifactId>changgou_service_goods_api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

订单服务启动类添加feign接口扫描

@EnableFeignClients(basePackages = "com.changgou.goods.feign")

订单服务新建CartController

@RestController
@CrossOrigin
@RequestMapping("/cart")
public class CartController {
​
    @Autowired
    private CartService cartService;
​
    /**
     * 添加购物车
     * @param skuId 
     * @param num
     * @return
     */
    @GetMapping("/add")
    public Result add(@RequestParam("skuId") String skuId, @RequestParam("num") Integer num){
​
        //暂时静态,后续动态获取
        String username = "itcast";
        cartService.add(skuId,num,username);
​
        return new Result(true, StatusCode.OK,"加入购物车成功");
​
    }
}

订单服务添加cartService,实现添加购物车

代码如下:

@Service
public class CartServiceImpl implements CartService {
​
    private static final String CART="Cart_";
​
    @Autowired
    private RedisTemplate redisTemplate;
​
    @Autowired
    private SkuFeign skuFeign;
​
    @Autowired
    private SpuFeign spuFeign;
​
    /**
     * 添加购物车
     * @param skuId
     * @param num
     */
    @Override
    public void add(String skuId, Integer num,String username) {
​
        /**
         * 1)查询redis中的数据
         * 2)如果redis中已经有了,则追加数量,重新计算金额
         * 3)如果没有,将商品添加到缓存
         */
        OrderItem orderItem = (OrderItem) redisTemplate.boundHashOps(CART+username).get(skuId);
        if (orderItem != null){
            //存在,刷新购物车
            orderItem.setNum(orderItem.getNum()+num);
            orderItem.setMoney(orderItem.getNum()*orderItem.getPrice());
            orderItem.setPayMoney(orderItem.getNum()*orderItem.getPrice());
        }else{
            //不存在,新增购物车
            Result<Sku> skuResult = skuFeign.findById(skuId);
            Sku sku = skuResult.getData();
            Spu spu = spuFeign.findByspuId(sku.getSpuId());
​
            //将SKU转换成OrderItem
            orderItem = this.sku2OrderItem(sku,spu,num);
        }
​
        //存入redis
        redisTemplate.boundHashOps(CART+username).put(skuId,orderItem);
​
​
    }
​
    //sku转换为orderItem
    private OrderItem sku2OrderItem(Sku sku, Spu spu, Integer num) {
        OrderItem orderItem = new OrderItem();
        orderItem.setSpuId(sku.getSpuId());
        orderItem.setSkuId(sku.getId());
        orderItem.setName(sku.getName());
        orderItem.setPrice(sku.getPrice());
        orderItem.setNum(num);
        orderItem.setMoney(num*orderItem.getPrice());       //单价*数量
        orderItem.setPayMoney(num*orderItem.getPrice());    //实付金额
        orderItem.setImage(sku.getImage());
        orderItem.setWeight(sku.getWeight()*num);           //重量=单个重量*数量
//分类ID设置
        orderItem.setCategoryId1(spu.getCategory1Id());
        orderItem.setCategoryId2(spu.getCategory2Id());
        orderItem.setCategoryId3(spu.getCategory3Id());
        return orderItem;
    }
}

测试添加购物车,效果如下:

请求地址localhost:9004/cart/add?skuId=100000022652&num=1

Redis缓存中已经有商品了

 购物车列表

 思路分析

接着我们实现一次购物车列表操作。因为存的时候是根据用户名往Redis中存储用户的购物车数据的,所以我们这里可以将用户的名字作为key去Redis中查询对应的数据。

代码实现

(1)控制层

com.changgou.order.controller.CartController类,添加购物车列表查询方法,代码如下:

/***
 * 查询用户购物车列表
 * @return
*/
@GetMapping(value = "/list")
public Map list(){
    //暂时静态,后续修改
    String username = "itcast";
    return cartService.list(username);
}

(2)业务层

业务层接口

com.changgou.order.service.CartService接口,添加购物车列表方法,代码如下:

/***
  * 查询用户的购物车数据
  * @return
  */
 Map list(String username);

业务层接口实现类

com.changgou.order.service.impl.CartServiceImpl类,添加购物车列表实现方法,代码如下:

/**
     * 获取购物车列表数据
     * @param username
     * @return
     */
    @Override
    public Map list(String username) {
        Map map = new HashMap();
​
        List<OrderItem> orderItemList = redisTemplate.boundHashOps(CART+username).values();
​
        map.put("orderItemList",orderItemList);
​
        //商品数量与总价格
        Integer totalNum = 0;
        Integer totalPrice = 0;
​
        for (OrderItem orderItem : orderItemList) {
            totalNum +=orderItem.getNum();
            totalPrice+=orderItem.getMoney();
        }
        map.put("totalNum",totalNum);
        map.put("totalPrice",totalPrice);
        return map;
    }

(3)测试

使用Postman访问 GET http://localhost:9004/cart/list ,效果如下:

posted @ 2021-08-10 13:38  1640808365  阅读(243)  评论(0编辑  收藏  举报