• 亿级流量大型电商平台——之购物车、商品下单实现


    购物车分析与实现

    购物车策略分析

    免登陆购物车

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

    身份验证购物车

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

    购物车特点

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

    购物车存储技术分析

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

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

    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" } ] });
    

    上述具体可参考如下:

    添加购物车关键代码:

    /***
     * 加入购物车
     * @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"
    

    添加购物车接口请求:

    查看购物车列表接口:

    商品下单分析与实现

    下单流程分析

    下单流程比较复杂,需要做很多个步骤,步骤如下:
    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;
    }
    

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

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


  • 相关阅读:
    struts2中form表单提交到action乱码
    struts2与ext一起用,找不到action
    Struts2学习
    Struts2之路第一天
    jsp&servlet 学生管理系统总结
    json初级
    AJAX
    问题---解决方式
    SQL语句优化
    Oracle内连接、外连接、右外连接、全外连接小总结
  • 原文地址:https://www.cnblogs.com/huangjianping/p/14994247.html
Copyright © 2020-2023  润新知