购物车

购物车数据的储存

购物车设计是每个电商项目中必不可缺的一环,不管登录与否,购物车都可以使用.那么购物车的数据我们存在哪里呢?
登录时,购物车的数据理所应当的存在redis数据库中,可是未登录时呢?
在这里我们给出了三个方案
1、当用户在未登录的情况下,将此购物车存入Cookie中, 在用户登陆的情况下,将购物车数据存入redis 。如果用户登陆时,Cookie中存在购物车数据,需要将Redis的购物车合并到redis中存储.
缺点:Cookie最大存放:4K;
2、当用户在未登录的情况下,将此购物车存入LocalStorage中, 在用户登陆的情况下,将购物车数据存入redis 。如果用户登陆时,LocalStorage中存在购物车数据,需要将Redis的购物车合并到redis中存储.
缺点:当用户清空浏览器缓存时,LocalStorage数据就没有了;
3、不管用户是否登录,都保存在Redis中;(1)当用户未登录的情况下,获取SessionID,以SessionID作为Redis的Key保存;(2)如果用户登录了,根据用户名来保存到Redis;(3)如果用户登录时,把SessionID中的Redis数据和用户名获取的Redis数据合并;
很明显第三种解决方案是最好的,在这里我们就按照第三种解决方案来设计未登录时的购物车

购物车实体类的设计

作为购物车页面,按照一般电商网站的设计,不同的卖家应该分为不同的区域,也就是说要按照商家的sellerId来分块展示购物车数据.在这里我们已sellerId来区分购物车数据,购物车实体类分为三个属性

    private String sellerId;//商家IDprivate String sellerName;//商家名称private List<TbOrderItem> orderItemList;//购物车明细

实现展示购物车数据方法:findCartList:

在商品详情页面的添加购物车追加点击事件,点击则触发添加购物车的方法,登录与否只是存入redis中的key是sessionId还是userId的区别而已

无论是否登录都要先判断cookie中是否有保存的sessionId,以此来判断未登录时是否购物车有数据,如果有在判断是否登录,如果登录则需要合并购物车

根据之前的设计,当用户未登录时我们以sessionId作为key保存购物车数据到redis数据库中,而为了避免sessionId关闭浏览器后丢失,我们采用把sessionId存入cookie中这个方法来保存sessionId.当用户登录后,应该把未登录时的购物车对象集合添加到登录时的购物车集合中,具体逻辑需要遍历未登录时的购物车集合把每个购物车对象依次判断是否在登录的购物车集合中已存在相同的sellerId,如果存在,在判断商品是否相同,如果商品相同,仅仅叠加数量,如果商品不同,则在orderItemList追加一个orderItem对象,如果sellerId都不同,则添加一个新的Cart对象

controller层代码

@RestController
@RequestMapping("/cart")
public class CartController {@Referenceprivate CartService cartService;@Autowiredprivate HttpSession session;@Autowiredprivate HttpServletRequest request;@Autowiredprivate HttpServletResponse response;@RequestMapping("/findCartList")public List<Cart> findCartList(){String userId = SecurityContextHolder.getContext().getAuthentication().getName();String sessionId = getSessionId();List<Cart> cartList_sessionId = cartService.findCartList(sessionId);//判断当前用户id是不是匿名用户,如果不是匿名用户则用userId作为key去查询redis数据库中的数据if(!"anonymousUser".equals(userId)) {List<Cart> cartList_userId = cartService.findCartList(userId);//购物车合并//如果cartList_sessionId的size不为0,则证明曾经未登录添加过购物车,这时我们要进行购物车合并if(cartList_sessionId.size()!=0) {//合并购物车cartList_userId = cartService.mergeCartList(cartList_userId, cartList_sessionId);//删除sessionId为key的数据库值cartService.clearRedisByKey(sessionId);//并且保存新的数据到数据库cartService.saveCartListBySessionToRedis(userId, cartList_userId);}return cartList_userId;}return cartList_sessionId;}private String getSessionId() {//直接从cookie中拿sessionId如果没有则创建一个sessionId扔到cookie中;String sessionId = CookieUtil.getCookieValue(request, "user_key", "utf-8");if(sessionId==null) {sessionId = session.getId();CookieUtil.setCookie(request, response, "user_key", sessionId, 24*60*60, "utf-8");}return sessionId;}@RequestMapping("/addCartList/{itemId}/{num}")@CrossOrigin({"http://item.pinyougou.com","www.pinyougou.com"})public Result addCartList(@PathVariable("itemId")Long itemId, @PathVariable("num")Integer num){//查询添加前购物车对象集合,传递参数使用try {List<Cart> oldCartList = findCartList();//调用方法进行添加List<Cart> cartList = cartService.addCartList(itemId,num,oldCartList);String userId = SecurityContextHolder.getContext().getAuthentication().getName();//同样根据是否登录来判断使用什么key来保存购物车列表到数据库if(!"anonymousUser".equals(userId)) {cartService.saveCartListBySessionToRedis(userId, cartList);}else {String sessionId = getSessionId();cartService.saveCartListBySessionToRedis(sessionId, cartList);}//调用方法保存购物车集合return new Result(true, "添加购物车成功");} catch (RuntimeException e) {return new Result(false, e.getMessage());} catch (Exception e) {e.printStackTrace();return new Result(false, "添加购物车失败");}}
}

serviceImpl层代码

@Service
public class CartServiceImpl implements CartService {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate TbItemMapper itemMapper;@Overridepublic List<Cart> findCartList(String sessionId) {//从redis数据库中根据sessionId或者userId作为key去取集合List<Cart> cartList = (List<Cart>) redisTemplate.boundHashOps("cartlist").get(sessionId);//如果为空则判断一下,因为如果集合为null则在页面遍历集合会报错if(cartList==null) {cartList = new ArrayList<Cart>(0);}return cartList;}@Overridepublic List<Cart> addCartList(Long itemId, Integer num, List<Cart> cartList) {TbItem tbItem = itemMapper.selectByPrimaryKey(itemId);//这里加一个判断,判断一下传过来的itemId是否是私自传过来的非法数据if(tbItem==null) {throw new RuntimeException("itemId数据非法");}String sellerId = tbItem.getSellerId();
//      1.添加的商品的sellerId与之前CartList列表中的某一个Cart对象中的sellerId作对比Cart cart = findCartFromCartListBySellerId(sellerId, cartList);
//         1.1如果存在某个Cart对象的sellerId与这个商品的sellerId相同时,获得这个Cart对象中的orderItemList集合,if(cart!=null) {
//              遍历这个集合并判断其中每一个orderItem对象的itemId是否相同List<TbOrderItem> orderItemList = cart.getOrderItemList();TbOrderItem orderItem =findOrderItemFromOrderItemListByItemId(itemId, orderItemList);
//            1.1.1如果相同,则证明之前添加过这个商品,并将传过来的num叠加上去,并更新小计价格if(orderItem!=null) {orderItem.setNum(orderItem.getNum()+num);orderItem.setTotalFee(new BigDecimal(orderItem.getNum()*orderItem.getPrice().doubleValue()));//如果此时的num属性为0则判断移除改orderItemif(orderItem.getNum()<=0) {orderItemList.remove(orderItem);//这是判断移除orderItem后orderItemList中是否还有数据,如果没有则移除整个Cart对象if(orderItemList.size()==0) {cartList.remove(cart);}}}else {
//            1.1.2如果不同,则证明没有添加过这个商品,把这个商品作为一个orderItem对象添加到orderItemList集合中orderItem = createOrderItem(orderItem, tbItem, itemId, num);cart.getOrderItemList().add(orderItem);}}else {
//         1.2如果不存在某个Cart对象的sellerId与之相同,则创建一个新的Cart对象并赋予其sellerId, sellerName,
//              orderItemList,并把这个Cart对象添加到CartList列表中cart = new Cart();cart.setSellerId(sellerId);cart.setSellerName(tbItem.getSeller());List<TbOrderItem> orderItemList = new ArrayList<>();TbOrderItem orderItem = null;orderItem = createOrderItem(orderItem, tbItem, itemId, num);cart.setOrderItemList(orderItemList);orderItemList.add(orderItem);cartList.add(cart);}return cartList;}private TbOrderItem createOrderItem(TbOrderItem orderItem, TbItem tbItem, Long itemId, Integer num) {//当第一次添加商品时,如果通过非法途径传入一个小于1的数字,则抛出一个异常if(num<1) {throw new RuntimeException("数量非法");}orderItem=new TbOrderItem();orderItem.setGoodsId(tbItem.getGoodsId());orderItem.setItemId(itemId);orderItem.setNum(num);orderItem.setPicPath(tbItem.getImage());orderItem.setPrice(tbItem.getPrice());orderItem.setSellerId(tbItem.getSellerId());orderItem.setTitle(tbItem.getTitle());orderItem.setTotalFee(new BigDecimal(orderItem.getNum()*orderItem.getPrice().doubleValue()));return orderItem;}
//用来遍历这个集合并判断其中每一个orderItem对象的itemId是否相同,如果有则返回一个orderItem对象private TbOrderItem findOrderItemFromOrderItemListByItemId(Long itemId, List<TbOrderItem> orderItemList) {for (TbOrderItem orderItem : orderItemList) {if(itemId.equals(orderItem.getItemId())) {return orderItem;}}return null;}
//用来遍历这个集合并判断其中每一个Cart对象的SellerId是否相同,如果有则返回一个Cart对象private Cart findCartFromCartListBySellerId(String sellerId, List<Cart> cartList) {for (Cart cart : cartList) {if(sellerId.equals(cart.getSellerId())){return cart;}}return null;}@Overridepublic void saveCartListBySessionToRedis(String sessionId, List<Cart> cartList) {redisTemplate.boundHashOps("cartlist").put(sessionId, cartList);}@Overridepublic List<Cart> mergeCartList(List<Cart> cartList_userId, List<Cart> cartList_sessionId) {//遍历这个未登录是添加的购物车集合for (Cart cart : cartList_sessionId) {//获得每个cart对象,并再获取其orderItemListList<TbOrderItem> orderItemList = cart.getOrderItemList();//遍历这个orderItemList,获取每一个orderItemfor (TbOrderItem orderItem : orderItemList) {//调用addCartList方法,把每一个orderItem对象添加到cartList中并返回cartList_userId = addCartList(orderItem.getItemId(), orderItem.getNum(), cartList_userId);}}return cartList_userId;}@Overridepublic void clearRedisByKey(String sessionId) {redisTemplate.boundHashOps("cartlist").delete(sessionId);}}

电商项目之购物车设计相关推荐

  1. 关于电商项目的购物车总结和购物车实现

    关于电商项目的购物车总结和购物车实现 本文中简述的购物车模仿京东的模式,用户没有登录,也可进行购物车的操作,如果用户登录了,则在数据库中操作购物车.我们基于存放在cookies里面. 先看添加到购物车 ...

  2. 一个电商项目的数据库设计实践(第一部分)(附源码)

    一次电商项目后台的数据库设计小结(第一部分)(附源码) 1.准备工作 2.用户实体 2.1 用户登陆表(customer_login) 2.2 用户信息表(customer_inf) 2.3 用户级别 ...

  3. SpringBoot电商项目之购物车下单(沙箱支付)

    目录 一.购物车结算前端功能实现 二.购物车结算后端功能实现 1.从session中获取购物车对象 2.筛选出要结算的订单项列表集合 3.订单页前台展示 三.结算页的下单前端 生成订单 1.前端相关处 ...

  4. 电商项目(一)---------Sku和Spu以及电商项目商品的设计思路

    一,在电商项目里面为了准确的描述商品的区别,我们抽象出来两个概念,Spu和Sku这两个概念. Spu(标准产品单位 ):一组具有共同属性的商品集 Sku(库存量单位):SPU商品集因具体特性不同而细分 ...

  5. 【愚公系列】2022年10月 微信小程序-电商项目-商品购物车功能实现

    文章目录 前言 一.商品购物车功能实现 二.效果 前言 在电商的核心交易流程中,购物车是其中非常重要的一环,它承担商品加购.价格计算.促销活动展示等功能,与会员系统.商品系统.库存系统.订单系统等紧密 ...

  6. 电商项目day16(购物车实现)

    今日目标: 理解购物车的思路 购物车登陆后存储到redis中 一.需求分析 数据结构分析: 购物车与商家相关联 我们由京东的案列,就是可以看出,不登录,也可以实现购物车的添加,不过天猫不可以,必须登陆 ...

  7. Vue3电商项目实战-购物车模块2【04-头部购物车-商品列表-本地、05-头部购物车-删除操作-本地、06-购物车页面-基础布局】

    文章目录 04-头部购物车-商品列表-本地 05-头部购物车-删除操作-本地 06-购物车页面-基础布局 04-头部购物车-商品列表-本地 目的:根据本地存储的商品获取最新的库存价格和有效状态. 大致 ...

  8. 电商项目可扩展性数据库设计与实现

    本场 Chat 主要讲小编在最近重构交易系统过程中的一些心得的系列文章,本场 Chat 主要讲从 PHP 版交易系统到 Java 版交易系统过程中数据库设计的改变,从业务设计到抽象设计,使数据库更加适 ...

  9. mysql电商类查询_GitHub - cntianjue/Estore: JavaWEB电商项目(mysql)

    申明:在原作者的基础上增加功能(适合初学者) 原作者地址:HTTPS://github.com/hsingyin/EStore -----致敬 EStore电脑商城 一.起步 简介 一个基于JavaW ...

最新文章

  1. 二十八、顺序存储二叉树
  2. 机器学习中的相似性度量 (转)
  3. 完美完全卸载Oracle 11g数据库
  4. 虚拟化精华问答 | 虚拟化会使管理更轻松吗?
  5. rsort php,php中rsort函数实例用法
  6. oracle用户删除了可以恢复吗,恢复用户误删除的没备份的Oracle数据文件
  7. 员工绩效评估的5个目标
  8. 别扔掉你的登机牌,黑客可以用它获取个人信息
  9. cf1009 C. Annoying Present
  10. 例题 8-4 传送中的车(Fabled Rook, UVa 11134)
  11. ASIHTTPRequest 状态栏网络等待指示器
  12. 武汉:“大象转身”,“中国车都”变“中国车谷”的二段跨越
  13. ArchSummit讲师专访:EMC研究院资深研究员陶隽谈实时数据分析
  14. OpenLayers 4 ol.source 详解
  15. 诺基亚A7Android,诺基亚四款新机齐曝光 你最期待哪一款?
  16. 红米note2能刷机没显示无服务器,红米Note2刷机之后一直停留在开机界面修复教程...
  17. The missing quarter of a million 消失的25万 | 经济学人20230311版社论高质量双语精翻
  18. Kubernetes Pod冗余策略
  19. 特殊人工智能英语教育
  20. 唯美高清自动404网站源码

热门文章

  1. 【正点原子FPGA连载】第七章Verilog HDL语法 -摘自【正点原子】新起点之FPGA开发指南_V2.1
  2. 分享个热血三国辅助脚本,教你热血三国手游多开
  3. 夏普中国否认出售电视业务:中国市场是核心阵地
  4. 【前端修炼场】 — 这些标签你学会了么?快速拿下 “hr”
  5. Stm32 - Printf重定向(不)使用微库(Keil MDK)
  6. 「竞品分析报告」不会写?不知从哪收集数据?请收下这篇竞品指南
  7. 剑三游戏计算机配置,剑网3重制版电脑配置需求 关于选电脑二三事
  8. 小峰峰的pat甲级刷题记录1020
  9. 《GAMES104-现代游戏引擎:从入门到实践》-02 学习笔记
  10. 在南方读研和在北方读研有多大差异?