首页 > 其他分享 >尚品汇-添加购物车实现(三十六)

尚品汇-添加购物车实现(三十六)

时间:2024-08-25 20:26:44浏览次数:13  
标签:三十六 skuId 用户 request userId 尚品 购物车 cartInfo

目录:

(1)购物车业务简介

(2)购物车模块搭建

(3)搭建service-cart服务

(4)功能—添加入购物车

(5)添加购物车功能开发

(1)购物车业务简介

购物车模块要能够存储顾客所选的的商品,记录下所选商品,还要能随时更新,当用户决定购买时,用户可以选择决定购买的商品进入结算页面。

  功能要求:

  1. 利用缓存提高性能。
  2. 未登录状态也可以存入购物车,一旦用户登录要进行合并操作。

流程分析:

(2)购物车模块搭建

购物车添加展示流程:

(3)搭建service-cart服务

修改配置pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>com.atguigu.gmall</groupId>
      <artifactId>service</artifactId>
      <version>1.0</version>
   </parent>

   <version>1.0</version>
   <artifactId>service-cart</artifactId>
   <packaging>jar</packaging>
   <name>service-cart</name>
   <description>service-cart</description>

<dependencies>
      <dependency>
        <groupId>com.atguigu.gmall</groupId>
        <artifactId>service-product-client</artifactId>
        <version>1.0</version>
      </dependency>
   </dependencies>

   <build>
      <finalName>service-cart</finalName>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>

</project>

 添加配置文件bootstrap.properties

spring.application.name=service-cart
spring.profiles.active=dev
spring.cloud.nacos.discovery.server-addr=192.168.200.129:8848
spring.cloud.nacos.config.server-addr=192.168.200.129:8848
spring.cloud.nacos.config.prefix=${spring.application.name}
spring.cloud.nacos.config.file-extension=yaml
spring.cloud.nacos.config.shared-configs[0].data-id=common.yaml

启动类

package com.atguigu.gmall.cart;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@ComponentScan(basePackages = "com.atguigu.gmall")
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "com.atguigu.gmall")
public class ServiceCartApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceCartApplication.class,args);
    }
}

(4)功能—添加入购物车

功能解析:

  1. 商品详情页添加购物车
  2. 添加购物车,用户可以不需要登录,如果用户没有登录,则生成临时用户id,购物车商品与临时用户id关联,当用户登录后,将临时用户id的购物车商品与登录用户id的商品合并
  3. 商品详情添加购物车时,先判断用户是否登录,如果没登录,再判断是否存在临时用户,如果cookie中也没有临时用户,则生成临时用户

商品详情页

商品详情添加购物车页面方法(/item/index.html):

addToCart() {

    // 判断是否登录和是否存在临时用户,如果都没有,添加临时用户

    if(!auth.isTokenExist() && !auth.isUserTempIdExist()) {

        auth.setUserTempId()

    }

    window.location.href = 'http://cart.gmall.com/addCart.html?skuId=' + this.skuId + '&skuNum=' + this.skuNum

}

服务网关处理

思路:既然userId是从服务网关统一传递过来的,那么临时用户id我们也可以从网关传递过来,改造网关

网关中获取临时用户id

在server-gateway 项目中添加

/**
 * 获取当前用户临时用户id
 * @param request
 * @return
 */
private String getUserTempId(ServerHttpRequest request) {
    String userTempId = "";
    List<String> tokenList = request.getHeaders().get("userTempId");
    if(null  != tokenList) {
        userTempId = tokenList.get(0);
    } else {
        MultiValueMap<String, HttpCookie> cookieMultiValueMap =  request.getCookies();
        HttpCookie cookie = cookieMultiValueMap.getFirst("userTempId");
        if(cookie != null){
            userTempId = URLDecoder.decode(cookie.getValue());
        }
    }
    return userTempId;
}

设置网关请求头

String userTempId = this.getUserTempId(request);

if(!StringUtils.isEmpty(userId) || !StringUtils.isEmpty(userTempId)) {
    if(!StringUtils.isEmpty(userId)) {
        //存储到request作用域
        request.mutate().header("userId", userId).build();
    }
    if(!StringUtils.isEmpty(userTempId)) {
        //存储到request作用域
        request.mutate().header("userTempId", userTempId).build();
    }
    //将现在的request 变成 exchange对象
    return chain.filter(exchange.mutate().request(request).build());
}

这里的代码可以获取临时用户id 

(5)添加购物车功能开发

 

创建实体

@Data
@ApiModel(description = "购物车")
public class CartInfo extends BaseEntity {
    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "用户id")
    private String userId;

    @ApiModelProperty(value = "skuid")
    private Long skuId;

    @ApiModelProperty(value = "放入购物车时价格")
    private BigDecimal cartPrice;

    @ApiModelProperty(value = "数量")
    private Integer skuNum;

    @ApiModelProperty(value = "图片文件")
    private String imgUrl;

    @ApiModelProperty(value = "sku名称 (冗余)")
    private String skuName;

    @ApiModelProperty(value = "isChecked")
    private Integer isChecked = 1;

    //实时价格 skuInfo.price
    BigDecimal skuPrice;

}

创建添加购物车接口

package com.atguigu.gmall.cart.service;

public interface CartService {
    // 添加购物车 用户Id,商品Id,商品数量。
    void addToCart(Long skuId, String userId, Integer skuNum);
}

定义业务需要使用的常量,RedisConst类
public static final String USER_KEY_PREFIX = "user:";
public static final String USER_CART_KEY_SUFFIX = ":cart";
public static final long USER_CART_EXPIRE = 30000;

添加购物车实现类 

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private RedisTemplate redisTemplate;


    @Override
public void addToCart(Long skuId, String userId, Integer skuNum) {
    //  获取缓存key
    String cartKey = getCartKey(userId);

    BoundHashOperations<String, String, CartInfo> boundHashOps = this.redisTemplate.boundHashOps(cartKey);
    CartInfo cartInfo = null;
    //包含的话更新数量
    if(boundHashOp
s.hasKey(skuId.toString())) {
        cartInfo = boundHashOps.get(skuId.toString());
        cartInfo.setSkuNum(cartInfo.getSkuNum()+skuNum);
        cartInfo.setIsChecked(1);
        cartInfo.setSkuPrice(productFeignClient.getSkuPrice(skuId));
        cartInfo.setUpdateTime(new Date());
    } else {
        //购物车不存在数据,存入新的数据

        cartInfo = new CartInfo();
        //  给cartInfo 赋值! 远程请求sku详情数据
        SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);

        //  给表的字段赋值!
        cartInfo.setUserId(userId);
        cartInfo.setSkuId(skuId);
        cartInfo.setCartPrice(skuInfo.getPrice());
        cartInfo.setSkuNum(skuNum);
        cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
        cartInfo.setSkuName(skuInfo.getSkuName());
        cartInfo.setCreateTime(new Date());
        cartInfo.setUpdateTime(new Date());
        //实时价格
        cartInfo.setSkuPrice(skuInfo.getPrice());
    }

    //存储
    boundHashOps.put(skuId.toString(), cartInfo);
    
}




// 获取购物车的key
private String getCartKey(String userId) {
        //定义key user:userId:cart
        return RedisConst.USER_KEY_PREFIX + userId +       RedisConst.USER_CART_KEY_SUFFIX;
    }



}

添加购物车控制器

package com.atguigu.gmall.cart.controller;

@RestController
@RequestMapping("api/cart")
public class CartApiController {

    @Autowired
    private CartService cartService;

    /**
     * 添加购物车
     * @param skuId
     * @param skuNum
     * @param request
     * @return
     */
    @RequestMapping("addToCart/{skuId}/{skuNum}")
    public Result addToCart(@PathVariable("skuId") Long skuId,
                            @PathVariable("skuNum") Integer skuNum,
                            HttpServletRequest request) {
        // 如何获取userId
        String userId = AuthContextHolder.getUserId(request);
        if (StringUtils.isEmpty(userId)) {
            // 获取临时用户Id
            userId = AuthContextHolder.getUserTempId(request);
        }
        cartService.addToCart(skuId, userId, skuNum);
        return Result.ok();
    }
}

未登录添加购物车:Redis存的key中的用户id是临时id

登录后key中用户id存的是登录的用户的id

 

标签:三十六,skuId,用户,request,userId,尚品,购物车,cartInfo
From: https://blog.csdn.net/dengfengling999/article/details/141369008

相关文章

  • 技术分享-商品篇-购物车【加购功能】(八)
    前言在上一篇文章技术分享-商城篇-购物车(七)中,我们聊了购物车设计逻辑,也说到其中加购体系,但是我觉得对于加购逻辑说的还是不够详细,所以就单开一篇文章对这个加购功能单独性聊一下,争取能把里面的逻辑和注意事项给说清楚(尽我本人所知所学的能力),因为加入购物车与立即购买功能......
  • 推荐系统三十六式学习笔记:工程篇.效果保证31|推荐系统的测试方法及常用指标介绍
    目录为什么要关注指标推荐系统的测试方法1.业务规则扫描2.离线模拟测试3.在线对比测试4.用户访谈常用指标1.系统有多好?假设你已经有了自己的推荐系统,这个系统已经上线。为什么要关注指标面对推荐系统这样一个有诸多复杂因素联动起作用的系统,要时时刻刻知道它好不......
  • 【vue讲解:购物车案例】
    1购物车案例1.1基本购物车<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><scriptsrc="./js/vue.js"></script><linkrel="styl......
  • 电子表格转身购物车:三步轻松实现
    最新技术资源(建议收藏)https://www.grapecity.com.cn/resources/在我们的项目当中,经常需要添加一些选择界面,让用户直观地进行交互,比如耗材、办公用品、设计稿或者其它可以选择的内容。在线商城的商品目录和购物车无疑是一种大家都很熟悉的交互方式,但是在实际开发中,我们可能会......
  • 前端Vue组件化开发:仿京东淘宝的加入购物车与立即购买弹框组件
    随着前端技术的飞速发展,组件化开发已经成为前端工程化不可或缺的一部分。它不仅能够降低代码的耦合度,提高开发效率,还能够极大地简化后期的维护和扩展工作。在复杂的业务场景下,组件化开发更是成为前端工程师的必备技能。本文将介绍一个基于Vue的前端组件——仿京东淘宝的加入购......
  • 微信小程序 - 最新详细实现 “餐厅食堂外卖点餐“ 全屏左右联动菜单列表功能界面,附带
    前言如果您需要“简约通用”的左右联动功能,请访问这篇文章。在微信小程序开发中,详解实现仿饿了么、美团外卖用户点餐左右联动界面,全屏适配左边菜单分类右侧商品菜单列表数据,顶部是搜索栏可搜索定位对应锚点位置及商品,左侧导航菜单点击时右侧商品跟着变化,反之列表滑动......
  • 第十节 JMeter基础-初级购物车【接口关联-鉴权】
    声明:本文所记录的仅本次操作学习到的知识点,其中商城IP错误,请自行更改。 背景:商城购物车可以添加数据,也可以删除数据。思路:登录后添加购物车,加入成功后查看购物车列表。购物车列表,随机删除,或者指定删除(需要特殊指定,例如购物车ID)。全部删除:依次读取购物车列表并删除。 1......
  • 【Django+Vue3 线上教育平台项目实战】购物车与订单模块的精简实现与数据安全策略
    文章目录前言一、购物车模块1.后端核心逻辑2.前端页面代码3.操作流程及演示二、订单模块1.订单模块模型类设计1.展示订单信息a.页面展示b.前端核心代码c.后端核心逻辑2.订单是否使用优惠券与积分a.页面展示b.前端核心代码3.订单支付方式a.页面展示b.前端核心代码4.......
  • 【Django】网上蛋糕项目商城-购物车和我的订单功能
    1.购物车功能在首页中的滚动栏的商品,热门商品,新品,以及商品详情中都有加入购物车按钮在models文件中创建购物车表,用于保存当前用户添加的商品信息#购物车表classShoppingCar(models.Model):#用户iduserId=models.IntegerField()#商品idgoodsId=......
  • 易优cms网站user功能:动态显示购物车、登录、注册、退出、会员中心的入口-Eyoucms
    user登录注册入口标签 [基础用法]名称:user功能:动态显示购物车、登录、注册、退出、会员中心的入口;语法:  {eyou:usertype='userinfo'}    <divid="{$field.htmlid}">       <ahref="{$field.loginurl}">登录</a>       <ahref="{$fi......