【Java 实战】通过Redis实现购物车功能
创始人
2024-04-07 13:34:41

项目场景:

通过Redis实现购物车,包括添加购物车、更新商品数量、删除购物车、结算验证库存等功能。

设计思路

1.数据存储

对于购物车,我们在Redis中需要存储的是用户和商品信息,数据结构类似于Java中Map>形式,将外层Map的key记为K,内层Map的key和value分别记为HK、HV

使用K来存储用户标识(例如:用户的ID)
使用HK存储商品标识(例如:商品ID)
使用HV存储购物车商品信息(例如:购物车中商品数量、价格、店铺信息等(根据自己业务需求))

Redis 中可以使用boundHashOps方法来实现:BoundHashOperations operations = stringRedisTemplate.boundHashOps(userId);

也可以使用Map itemMap = redisTemplate.opsForValue().get(userId);来实现

2.功能结构图

3.功能描述

在添加购物车时需要用户先登录(web界面后台可以通过session获取用户id),这里直接默认传入用户id

添加购物车

添加购物车,需要判断购物车里是否存在该商品,存在则该商品数量增加,不存在需要查询该商品然后将商品加入到购物车,方法:operations.put(key,value);

@Override
public ApiResponse addCart(OperateVo vo) {// 用户购物车存储的keyString key = CART_KEY + vo.getUserId();// 获取用户购物车数据BoundHashOperations cartMap = stringRedisTemplate.boundHashOps(key);// 判断商品是否存在String cart = (String) cartMap.get(vo.getSkuId());if (StringUtils.isBlank(cart)) {// 商品不存在,则添加商品信息Item item = itemService.getBySkuId(vo.getSkuId());// 添加购物车商品数量item.setNum(vo.getNum());cartMap.put(vo.getSkuId(), JSON.toJSONString(item));} else {// 商品存在,则数量增加Item item = JSON.parseObject(cart, Item.class);item.setNum(item.getNum() + vo.getNum());cartMap.put(vo.getSkuId(), JSON.toJSONString(item));}return ApiResponse.ok();
}

获取购物车信息

通过用户id查询该用户的购物车信息,方法:operations.get(key);

@Override
public ApiResponse showCart(OperateVo vo) {CartEntry cartEntry = new CartEntry();// 用户购物车存储的keyString key = CART_KEY + vo.getUserId();BoundHashOperations cartMap = stringRedisTemplate.boundHashOps(key);// 获取所有的购物车数据List cartList = cartMap.values();if (CollectionUtils.isNotEmpty(cartList)) {List items = new ArrayList<>();cartList.forEach(item -> {String objStr = (String) item;Item carItem = JSON.parseObject(objStr, Item.class);items.add(carItem);});cartEntry.setItems(items);}return ApiResponse.ok(cartEntry);
}
 

修改商品数量

对购物车中商品的数量进行修改,方法:operations.put(key);

@Override
public ApiResponse updateCartNum(OperateVo vo) {// 用户购物车存储的keyString key = CART_KEY + vo.getUserId();BoundHashOperations cartMap = stringRedisTemplate.boundHashOps(key);String cart = (String) cartMap.get(vo.getSkuId());Item item = JSON.parseObject(cart, Item.class);item.setNum(vo.getNum());cartMap.put(vo.getSkuId(), JSON.toJSONString(item));return ApiResponse.ok();
}

删除购物车

删除购物车中的商品,或者清空用户的购物车,方法分别为:operations.delete(key)、stringRedisTemplate.delete(userId);

@Override
public ApiResponse delCart(OperateVo vo) {// 用户购物车存储的keyString key = CART_KEY + vo.getUserId();BoundHashOperations cartMap = stringRedisTemplate.boundHashOps(key);cartMap.delete(vo.getSkuId());return ApiResponse.ok();
}

结算页面验证购物车商品库存

添加晚购物车后,点击去结算,验证商品库存是否充足

@Override
public ApiResponse checkNumCart(OperateVo vo) {CartEntry cartEntry = new CartEntry();// 用户购物车存储的keyString key = CART_KEY + vo.getUserId();BoundHashOperations cartMap = stringRedisTemplate.boundHashOps(key);if (vo != null) {List items = new ArrayList<>();vo.getSkuIds().forEach(id -> {String cart = (String) cartMap.get(id);Item redisItem = JSON.parseObject(cart, Item.class);// 获取商品库存数量Item item = itemService.getBySkuId(vo.getSkuId());if (item.getNum() < redisItem.getNum()) {// 库存不足redisItem.setEnough(false);}items.add(redisItem);});cartEntry.setItems(items);}return ApiResponse.ok(cartEntry);
}

代码实现:

好啦,购物车操作的功能到这里已经差不多啦,个人觉得后面购物车下单、拆单及退款处理才是难点😏

接下来,又到了愉快的贴代码环节了,废话不多说,直接上代码:

CartEntry.java

/*** 购物车** @author:MaodeShu* @date:2022-11-12 11:24*/
@Data
public class CartEntry {List items;// 商品列表BigDecimal totalPrice; // 总结int totalNum; // 总数}

Item.java

/*** 商品信息** @author:MaodeShu* @date:2022-11-12 11:24*/
@Data
public class Item extends ItemEntity{// 商品是否充足private Boolean enough = true;
}

ItemEntity.java

/*** 商品实体信息** @author:MaodeShu* @date:2022-11-12 11:24*/
@Data
@TableName("item_sku_info")
public class ItemEntity {private String productId;// 产品idprivate String productName; // 产品名称private String skuId;// 商品skuIdprivate String skuName; // 商品skuNameprivate String shopId;// 店铺idprivate String shopName;// 店铺名private String shopLog; // 店铺logoprivate String coverUrl; // 商品图private BigDecimal sellPrice; // 售价private Integer num; // 库存
}

OperateVo.java

/*** 操作购物车信息** @author:MaodeShu* @date:2022-11-12 11:24*/
@Data
public class OperateVo {private String userId;// 用户idprivate String skuId; // 商品skuIdprivate Integer num;// 数量private List skuIds; // 商品skuId列表(选择购物车时使用)
}

CartServiceImpl.java

@Service
public class CartServiceImpl implements CartService {private final String CART_KEY = "cart:";@Resourceprivate RedisTemplate stringRedisTemplate;@Resourceprivate ItemInfoService itemService;@Overridepublic ApiResponse addCart(OperateVo vo) {// 用户购物车存储的keyString key = CART_KEY + vo.getUserId();// 获取用户购物车数据BoundHashOperations cartMap = stringRedisTemplate.boundHashOps(key);// 判断商品是否存在String cart = (String) cartMap.get(vo.getSkuId());if (StringUtils.isBlank(cart)) {// 商品不存在,则添加商品信息Item item = itemService.getBySkuId(vo.getSkuId());// 添加购物车商品数量item.setNum(vo.getNum());cartMap.put(vo.getSkuId(), JSON.toJSONString(item));} else {// 商品存在,则数量增加Item item = JSON.parseObject(cart, Item.class);item.setNum(item.getNum() + vo.getNum());cartMap.put(vo.getSkuId(), JSON.toJSONString(item));}return ApiResponse.ok();}@Overridepublic ApiResponse showCart(OperateVo vo) {CartEntry cartEntry = new CartEntry();// 用户购物车存储的keyString key = CART_KEY + vo.getUserId();BoundHashOperations cartMap = stringRedisTemplate.boundHashOps(key);// 获取所有的购物车数据List cartList = cartMap.values();if (CollectionUtils.isNotEmpty(cartList)) {List items = new ArrayList<>();cartList.forEach(item -> {String objStr = (String) item;Item carItem = JSON.parseObject(objStr, Item.class);items.add(carItem);});cartEntry.setItems(items);}return ApiResponse.ok(cartEntry);}@Overridepublic ApiResponse updateCartNum(OperateVo vo) {// 用户购物车存储的keyString key = CART_KEY + vo.getUserId();BoundHashOperations cartMap = stringRedisTemplate.boundHashOps(key);String cart = (String) cartMap.get(vo.getSkuId());Item item = JSON.parseObject(cart, Item.class);item.setNum(vo.getNum());cartMap.put(vo.getSkuId(), JSON.toJSONString(item));return ApiResponse.ok();}@Overridepublic ApiResponse delCart(OperateVo vo) {// 用户购物车存储的keyString key = CART_KEY + vo.getUserId();BoundHashOperations cartMap = stringRedisTemplate.boundHashOps(key);cartMap.delete(vo.getSkuId());return ApiResponse.ok();}@Overridepublic ApiResponse checkNumCart(OperateVo vo) {CartEntry cartEntry = new CartEntry();// 用户购物车存储的keyString key = CART_KEY + vo.getUserId();BoundHashOperations cartMap = stringRedisTemplate.boundHashOps(key);if (vo != null) {List items = new ArrayList<>();vo.getSkuIds().forEach(id -> {String cart = (String) cartMap.get(id);Item redisItem = JSON.parseObject(cart, Item.class);// 获取商品库存数量Item item = itemService.getBySkuId(vo.getSkuId());if (item.getNum() < redisItem.getNum()) {// 库存不足redisItem.setEnough(false);}items.add(redisItem);});cartEntry.setItems(items);}return ApiResponse.ok(cartEntry);}
}
 

总结:

以上就是今天要讲的内容,本文仅仅简单介绍了如何通过Redis实现购物车功能,以上方法亲测有效,希望能给大家一个参考。

创作不易,关注💖、点赞👍、收藏🎉就是对作者最大的鼓励👏,欢迎在下方评论留言🧐

相关内容

热门资讯

最新或2023(历届)小学安全... 小学安全手抄报的图片参考  小学安全手抄报参考图(1)  小学安全手抄报参考图(2)  小学安全手抄...
最新或2023(历届)小学安全... 小学安全教育手抄报的图片参考  小学安全教育手抄报参考图(1)  小学安全教育手抄报参考图(2)  ...
最新或2023(历届)小学安全... 小学安全教育手抄报的图片参考  小学安全教育手抄报参考图(1)  小学安全教育手抄报参考图(2)  ...
最新或2023(历届)五年级安... 五年级安全手抄报的图片参考  五年级安全手抄报参考图(1)  五年级安全手抄报参考图(2)  五年级...
寒假生活的手抄报_最新或202...  关于寒假的作文一  寒假将过,寒假中的点点滴滴,磕磕绊绊都历历在目。寒假里的一件件事犹如天上的星星...