购物车分析与实现

购物车策略分析

免登陆购物车

用户不登录也能使用购物车,以前京东使用的就是这种方案,现在已经改为身份验证购物车模式,因为这种模式数据更安全。
优点:用户不登录也能使用购物车,给用户带来了方便
缺点:数据混乱,数据丢失概率大

身份验证购物车

用户必须登录才能使用购物车,天猫一直在使用这种方案。
优点:数据安全,不易丢失。
缺点:用户使用不方便,必须有账号、必须登录。

购物车特点

1、使用购物车的群体大
2、查询购物车的频率高、操作购物车的频率 高
3、数据不存在交易操作,安全级别不用太高
4、存储时间久
5、购物车以用户为单位进行存储

购物车存储技术分析

1、免登陆购物车,数据可存储在客户端,例如Cookie、LocalStorage、WebSQL,但都存在跨域问题。

2、身份校验购物车,数据可存储在非关系型数据可,例如MongoDB,tair,不建议使用Redis,因为购物车量大。如果设计永久保存购物车数据,可以使用MongoDB或者tair,他们都可以进行大规模扩容。

购物车流程分析

电商购物车redis 电商购物车用户_docker


docker安装mongodb

docker run -d  -p 27017:27017 --name mongodb -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=123456 mongo

进入容器

docker exec -it mongodb /bin/bash

登录mongo,登录的数据库是admin数据库

mongo 192.168.0.201:27017 -u 'admin' -p '123456' --authenticationDatabase 'admin'

创建数据库

use shop
#创建用户
#账号:root
#密码:123456
#角色:root
#管理数据库:admin
db.createUser({ user: 'sh', pwd: '123456', roles: [ { role: "dbOwner", db: "shop" } ] });

上述具体可参考如下:

电商购物车redis 电商购物车用户_电商购物车redis_02


添加购物车关键代码:

/***
 * 加入购物车
 * @param id
 * @param userName
 * @param num:当前商品加入购物车总数量
 * @return
 */
@Override
public void add(String id, String userName, Integer num) {
    //ID 不能冲突
    //1)删除当前ID对应的商品之前的购物车记录
    cartMapper.deleteById(userName+id);

    if(num>0){
        //2)根据ID查询Sku详情
        RespResult<Sku> skuResp = skuFeign.one(id);

        //3)将当前ID商品对应的数据加入购物车(存入到MongoDB)
        Sku sku= skuResp.getData();
        Cart cart = new Cart(userName+id,userName,sku.getName(),sku.getPrice(),sku.getImage(),id,num);
        cartMapper.save(cart);
    }
}
public interface CartMapper extends MongoRepository<Cart,String> {
}

微服务配置文件:

server:
  port: 8087
spring:
  application:
    name: mall-cart
  cloud:
    nacos:
      config:
        file-extension: yaml
        server-addr: 192.168.0.201:8848
      discovery:
        #Nacos的注册地址
        server-addr: 192.168.0.201:8848
  data:
    #MongoDB配置
    mongodb:
      uri: mongodb://sh:123456@192.168.0.201:27017/shop
  main:
    allow-bean-definition-overriding: true
#日志配置
logging:
  pattern:
    console: "%msg%n"

添加购物车接口请求:

电商购物车redis 电商购物车用户_数据_03


查看购物车列表接口:

电商购物车redis 电商购物车用户_数据_04

商品下单分析与实现

下单流程分析

下单流程比较复杂,需要做很多个步骤,步骤如下:
1、根据用户勾选的购物车ID查询购物车记录
2、实现库存递减
3、库存递减成功后,将购物车商品存入到订单明细中
4、添加订单
5、删除当前操作的购物车数据

数据表设计与关键代码实现

订单表设计:

CREATE TABLE `order` (
  `id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT '订单id',
  `total_num` int(11) DEFAULT NULL COMMENT '数量合计',
  `moneys` int(11) DEFAULT NULL COMMENT '金额合计',
  `pay_type` varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT '支付类型,1、在线支付、0 货到付款',
  `create_time` datetime DEFAULT NULL COMMENT '订单创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '订单更新时间',
  `pay_time` datetime DEFAULT NULL COMMENT '付款时间',
  `consign_time` datetime DEFAULT NULL COMMENT '发货时间',
  `end_time` datetime DEFAULT NULL COMMENT '交易完成时间',
  `username` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '用户名称',
  `recipients` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人',
  `recipients_mobile` varchar(12) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人手机',
  `recipients_address` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人地址',
  `weixin_transaction_id` varchar(30) COLLATE utf8_bin DEFAULT NULL COMMENT '交易流水号',
  `order_status` int(1) DEFAULT NULL COMMENT '订单状态,0:未完成,1:已完成,2:已退货',
  `pay_status` int(1) DEFAULT NULL COMMENT '支付状态,0:未支付,1:已支付,2:支付失败',
  `is_delete` int(1) DEFAULT NULL COMMENT '是否删除',
  PRIMARY KEY (`id`),
  KEY `create_time` (`create_time`),
  KEY `status` (`order_status`),
  KEY `payment_type` (`pay_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

订单明细表设计:

CREATE TABLE `order_sku` (
  `id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT 'ID',
  `category_one_id` int(11) DEFAULT NULL COMMENT '1级分类',
  `category_two_id` int(11) DEFAULT NULL COMMENT '2级分类',
  `category_three_id` int(11) DEFAULT NULL COMMENT '3级分类',
  `spu_id` varchar(60) COLLATE utf8_bin DEFAULT NULL COMMENT 'SPU_ID',
  `sku_id` varchar(60) COLLATE utf8_bin DEFAULT NULL COMMENT 'SKU_ID',
  `order_id` varchar(50) COLLATE utf8_bin 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 '总金额',
  `image` varchar(200) 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;

具体代码实现:

/***
 * 添加订单
 */
public Boolean add(Order order) {
    //1.查询购物车记录
    RespResult<List<Cart>> cartResp = cartFeign.list(order.getCartIds());
    List<Cart> carts = IterableConverter.toList(cartResp.getData());
    if(carts.size()==0){
        return false;
    }
    //2.库存递减   20000  成功
    skuFeign.decount(carts);

    //3.增加订单明细
    int totlNum = 0;    //商品个数
    int payMoney = 0;   //支付总金额
    for (Cart cart : carts) {
        //类型转换
        OrderSku orderSku = JSON.parseObject(JSON.toJSONString(cart), OrderSku.class);
        orderSku.setId(IdWorker.getIdStr());
        orderSku.setMoney(orderSku.getPrice()*orderSku.getNum());
        orderSku.setSkuId(cart.getSkuId());
        orderSku.setOrderId(order.getId());
        orderSkuMapper.insert(orderSku);

        //统计数据
        totlNum+=cart.getNum();
        payMoney+=orderSku.getMoney();
    }
    //4.增加订单
    order.setTotalNum(totlNum);
    order.setMoneys(payMoney);
    orderMapper.insert(order);

    //5.删除购物车记录
    cartFeign.delete(order.getCartIds());
    return true;
}

扩展——电商交易数据模型

电商购物车redis 电商购物车用户_电商购物车redis_05

扩展——电商交易下单流程

电商购物车redis 电商购物车用户_电商购物车redis_06


电商购物车redis 电商购物车用户_电商购物车redis_07