购物车

购物车

一、购物车需求

1、需求描述

  • 用户可以在登录状态下将商品添加到购物车【用户购物车/在线购物车】
    • 放入数据库
    • mongodb
    • 放入 redis(采用
      登录以后, 会将临时购物车的数据全部合并过来, 并清空临时购物车
  • 用户可以在未登录状态下将商品添加到购物车【游客购物车/离线购物车/临时购物车】
    • 放入 localstorage(客户端存储, 后台不存)
    • cookie
    • WebSQL
    • 放入 redis(采用)
      浏览器即使关闭, 下次进入, 临时购物车数据都在
  • 用户可以使用购物车一起结算下单
  • 给购物车添加商品
  • 用户可以查询自己的购物车
  • 用户可以在购物车中修改购买商品的数量。
  • 用户可以在购物车中删除商品。
  • 选中不选中商品
  • 在购物车中展示商品优惠信息
  • 提示购物车商品价格变化

2、数据结构

在这里插入图片描述

因此每一个购物项信息, 都是一个对象, 基本字段包括:

{
    skuId: 2131241,
    check: true,
    title: "Apple iphone.....",
    defaultImage: "...",
    price: 4999,
    count: 1,
    totalPrice: 4999,
    skuSaleVO: {...}
}

另外, 购物车中不止一条数据, 因此最终会是对象的数组。 即:

[
    {...},{...},{...}
]
  • 数据存储方式
    购物车是一个读多写多的场景,因此放入数据库并不合适,但购物车又是需要持久化,因此这里我们选用redis存储购物车数据。

  • 数据存储结构
    一个购物车是由多个购物项组成的,但是我们用List进行存储并不合适,因为使用List查找某个购物项时需要挨个遍历每个购物项,会造成大量时间损耗,为保证查找速度,我们使用hash进行存储

  • 首先不同用户应该有独立的购物车, 因此购物车应该以用户的作为 key 来存储, Value 是用户的所有购物车信息。 这样看来基本的k-v结构就可以了。

  • 但是, 我们对购物车中的商品进行增、 删、 改操作, 基本都需要根据商品 id 进行判断,为了方便后期处理, 我们的购物车也应该是k-v结构, key 是商品 id, value 才是这个商品的购物车信息。

    综上所述, 我们的购物车结构是一个双层 Map: Map<String,Map<String,String>>

  • 第一层 Map, Key 是用户 id

  • 第二层 Map, Key 是购物车中商品 id, 值是购物项数据

3、流程

参照京东

在这里插入图片描述

user-key 是随机生成的 id, 不管有没有登录都会有这个 cookie 信息。
两个功能: 新增商品到购物车、 查询购物车。
新增商品: 判断是否登录

  • 是: 则添加商品到后台 Redis 中, 把 user 的唯一标识符作为 key。
  • 否: 则添加商品到后台 redis 中, 使用随机生成的 user-key 作为 key。

查询购物车列表: 判断是否登录

  • 否: 直接根据 user-key 查询 redis 中数据并展示
  • 是: 已登录, 则需要先根据 user-key 查询 redis 是否有数据。
    • 有: 需要提交到后台添加到 redis, 合并数据, 而后查询。
    • 否: 直接去后台查询 redis, 而后返回

二、临时购物车

/**
* 获取到我们要操作的购物车
* @return
*/
private BoundHashOperations<String, Object, Object> getCartOps() {
UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
String cartKey = "";
if (userInfoTo.getUserId() != null) {
//gulimall:cart:1
cartKey = CART_PREFIX + userInfoTo.getUserId();
} else {
cartKey = CART_PREFIX + userInfoTo.getUserKey();
} B
oundHashOperations<String, Object, Object> operations =
redisTemplate.boundHashOps(cartKey);
return operations;
}

三、登录购物车

@Override
public Cart getCart() throws ExecutionException, InterruptedException {
Cart cart = new Cart();
UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
if(userInfoTo.getUserId()!=null){
//1、 登录
String cartKey =CART_PREFIX+ userInfoTo.getUserId();
//2、 如果临时购物车的数据还没有进行合并【合并购物车】
String tempCartKey = CART_PREFIX + userInfoTo.getUserKey();
List<CartItem> tempCartItems = getCartItems(tempCartKey);
if(tempCartItems!=null){
//临时购物车有数据, 需要合并
for (CartItem item : tempCartItems) {
addToCart(item.getSkuId(),item.getCount());
} //
清除临时购物车的数据
clearCart(tempCartKey);
} //
3、 获取登录后的购物车的数据【包含合并过来的临时购物车的数据, 和登录后的购
物车的数据】
List<CartItem> cartItems = getCartItems(cartKey);
cart.setItems(cartItems);
}else{
//2、 没登录
String cartKey =CART_PREFIX+ userInfoTo.getUserKey();
//获取临时购物车的所有购物项
List<CartItem> cartItems = getCartItems(cartKey);
cart.setItems(cartItems);
} r
eturn cart;
}
posted @ 2022-03-16 20:13  chenfl  阅读(236)  评论(0编辑  收藏  举报