欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 锐评 > 谷粒商城实战笔记-240~243-商城业务-购物车-页面环境搭建

谷粒商城实战笔记-240~243-商城业务-购物车-页面环境搭建

2024/10/25 2:26:10 来源:https://blog.csdn.net/epitomizelu/article/details/141463277  浏览:    关键词:谷粒商城实战笔记-240~243-商城业务-购物车-页面环境搭建

文章目录

  • 一,页面调整
    • 1,详情页增加“加入购物车”按钮
  • 二,添加购物车后台实现
      • 详细步骤
      • 异步处理的优点
  • 三,解决加购重复提交问题

这部分的主要内容:

  • 从product模块的详情页点击加入购物车,发送请求到cart购物车模块,添加成功后,跳转到success页面。
  • 详情页点击和首页点击我的购物车,向购物车服务发送请求,挑战到cartItem页面。
  • success页面点击去购物车结算跳转到结算页(即购物车列表页)
  • 完成添加购物车的后台逻辑
  • 解决重复提交的问题
    在这里插入图片描述

包含下面课程:

  • 240-商城业务-购物车-页面环境搭建
  • 241-商城业务-购物车-添加购物车
  • 242-商城业务-购物车-添加购物车细节
  • 243-商城业务-购物车-RedirectAttribute

一,页面调整

1,详情页增加“加入购物车”按钮

在这里插入图片描述
点击按钮向购物车服务发生请求。

加购成功后,跳转到success界面。

二,添加购物车后台实现

后台Service了一个名为 addToCart 的方法,用于将指定的商品添加到用户的购物车中。

添加到购物车中的主要逻辑如下:

  • 判断是已登录用户还是临时用户,不同类型的用户的redis key不同
  • redis中查询是否已经存在该skuId对应的商品
  • 如果存在,把该商品的数量加上页面上的值
  • 如果不存在,要调用远程接口查询sku的基本信息和销售属性信息,然后以skuid为key保存到redis中
 public CartItemVo addToCart(Long skuId, Integer num) throws ExecutionException, InterruptedException {//拿到要操作的购物车信息BoundHashOperations<String, Object, Object> cartOps = getCartOps();//判断Redis是否有该商品的信息String productRedisValue = (String) cartOps.get(skuId.toString());//如果没有就添加数据if (StringUtils.isEmpty(productRedisValue)) {//2、添加新的商品到购物车(redis)CartItemVo cartItemVo = new CartItemVo();//开启第一个异步任务CompletableFuture<Void> getSkuInfoFuture = CompletableFuture.runAsync(() -> {//1、远程查询当前要添加商品的信息R productSkuInfo = productFeignService.getInfo(skuId);SkuInfoVo skuInfo = productSkuInfo.getData("skuInfo", new TypeReference<SkuInfoVo>() {});//数据赋值操作cartItemVo.setSkuId(skuInfo.getSkuId());cartItemVo.setTitle(skuInfo.getSkuTitle());cartItemVo.setImage(skuInfo.getSkuDefaultImg());cartItemVo.setPrice(skuInfo.getPrice());cartItemVo.setCount(num);}, executor);//开启第二个异步任务CompletableFuture<Void> getSkuAttrValuesFuture = CompletableFuture.runAsync(() -> {//2、远程查询skuAttrValues组合信息List<String> skuSaleAttrValues = productFeignService.getSkuSaleAttrValues(skuId);cartItemVo.setSkuAttrValues(skuSaleAttrValues);}, executor);//等待所有的异步任务全部完成CompletableFuture.allOf(getSkuInfoFuture, getSkuAttrValuesFuture).get();String cartItemJson = JSON.toJSONString(cartItemVo);cartOps.put(skuId.toString(), cartItemJson);return cartItemVo;} else {//购物车有此商品,修改数量即可CartItemVo cartItemVo = JSON.parseObject(productRedisValue, CartItemVo.class);cartItemVo.setCount(cartItemVo.getCount() + num);//修改redis的数据String cartItemJson = JSON.toJSONString(cartItemVo);cartOps.put(skuId.toString(),cartItemJson);return cartItemVo;}}
  1. 获取购物车操作对象:

    • 使用 getCartOps() 方法获取 Redis 中购物车相关的 BoundHashOperations 对象,用于后续的读写操作。
  2. 检查商品是否已经在购物车中:

    • 从 Redis 中查询当前商品 skuId 是否已经存在于购物车中。
    • 如果商品不存在,则需要从远程服务获取商品信息并将其添加到购物车;如果存在,则直接更新商品的数量。
  3. 商品不在购物车中的处理流程:

    • 创建一个新的 CartItemVo 实例。
    • 异步调用远程服务获取商品的基本信息,并填充到 CartItemVo 中。
    • 异步调用远程服务获取商品的属性值列表,并填充到 CartItemVo 中。
    • 等待所有异步任务完成。
    • CartItemVo 序列化为 JSON 字符串并存入 Redis。
  4. 商品已在购物车中的处理流程:

    • 从 Redis 中读取已存在的 CartItemVo 并反序列化。
    • 更新商品的数量。
    • 将更新后的 CartItemVo 再次序列化为 JSON 字符串并存回 Redis。

详细步骤

  1. 获取购物车操作对象:

    • 调用 getCartOps() 方法获取购物车的 BoundHashOperations 对象。
  2. 检查商品是否存在:

    • 检查商品是否已经在 Redis 购物车中。
  3. 商品不存在时:

    • 创建 CartItemVo 实例。
    • 使用 CompletableFuture 异步获取商品信息和属性值。
    • 等待所有异步任务完成。
    • CartItemVo 序列化并存入 Redis。
  4. 商品已存在时:

    • 从 Redis 获取 CartItemVo
    • 修改商品的数量。
    • 将更新后的 CartItemVo 序列化并存入 Redis。

异步处理的优点

  • 提高性能:通过异步处理,减少了等待远程服务响应的时间,从而提高了整体性能。
  • 提高响应速度:由于异步处理不需要等待所有任务完成就可以返回结果,因此能更快地响应客户端。

三,解决加购重复提交问题

我们加购的提交的地址是:

http://cart.gulimall.com/addCartItem?skuId=1&num=2

这个请求发出后,后台执行加购逻辑,如果直接返回success页面。

	@GetMapping(value = "/addCartItem")public String addToCart() {return "success";}

会导致一个问题,如果用户刷新这个页面,就会重复提交加购请求,这个商品会被重复加购,导致不好的客户体验。

所以不能把这个地址暴露在浏览器的地址栏。

参考京东的做法,我们可以在用户点击加购请求后不直接返回success页面,而是让浏览器重定向到一个新的地址,这个地址会返回sucess页面,但是这个地址不会有其他的业务逻辑。

具体的逻辑是这样:

  • 用户点击加购,浏览器发出加购请求
  • 后台接收处理加购请求,让浏览器重定向到一个新的地址
  • 这个地址对应的接口会返回success页面,但不执行其他逻辑,用户刷新不会导致加购的重复提交

代码如下。

@GetMapping(value = "/addCartItem")public String addCartItem(@RequestParam("skuId") Long skuId,@RequestParam("num") Integer num,RedirectAttributes attributes) throws ExecutionException, InterruptedException {cartService.addToCart(skuId,num);attributes.addAttribute("skuId",skuId);return "redirect:http://cart.gulimall.com/addToCartSuccessPage.html";}/*** 跳转到添加购物车成功页面* @param skuId* @param model* @return*/@GetMapping(value = "/addToCartSuccessPage.html")public String addToCartSuccessPage(@RequestParam("skuId") Long skuId,Model model) {//重定向到成功页面。再次查询购物车数据即可CartItemVo cartItemVo = cartService.getCartItem(skuId);model.addAttribute("cartItem",cartItemVo);return "success";}

如果addCartItem接口直接返回success界面,那么浏览器地址栏的地址就是:

http://cart.gulimall.com/addCartItem?skuId=1&num=2

用户刷新浏览器,就会提交一个加购请求。

如果addCartItem接口重定向到其他接口,那么浏览器显示的地址就是:

http://cart.gulimall.com/addToCartSuccessPage.html?skuId=1

用户刷新页面,并不会导致加购的重复提交。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com