购物车分析与实现
购物车策略分析
免登陆购物车
用户不登录也能使用购物车,以前京东使用的就是这种方案,现在已经改为身份验证购物车模式,因为这种模式数据更安全。
优点:用户不登录也能使用购物车,给用户带来了方便
缺点:数据混乱,数据丢失概率大
身份验证购物车
用户必须登录才能使用购物车,天猫一直在使用这种方案。
优点:数据安全,不易丢失。
缺点:用户使用不方便,必须有账号、必须登录。
购物车特点
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;
}
扩展——电商交易数据模型
扩展——电商交易下单流程