当前位置: 首页 > news >正文

【业务功能篇97】微服务-springcloud-springboot-电商购物车模块-获取当前登录用户的购物车信息

购物车功能

一、购物车模块

1.创建cart服务

  我们需要先创建一个cart的微服务,然后添加相关的依赖,设置配置,放开注解。

<dependencies><dependency><groupId>com.msb.mall</groupId><artifactId>mall-commons</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

然后属性文件中的配置

server.port=40000
spring.application.name=mall-cartspring.cloud.nacos.discovery.server-addr=192.168.56.100:8848
spring.thymeleaf.cache=false

然后再添加配置中心的配置:bootstrap.yml文件

spring.application.name=mall-cart
spring.cloud.nacos.config.server-addr=192.168.56.100:8848

放开注册中心的注解

image.png

2.Nginx配置

  首先在windows中的host指定对应域名

image.png

拷贝对应的静态资源到Nginx的static/cart目录中

image.png

然后修改Nginx的配置文件

image.png

然后重启nginx服务

docker restart nginx

3.配置网关服务

  Nginx接收了 cart.msb.com这个域名的访问,那么会把服务反向代理给网关服务,这时网关服务就需要把该请求路由到购物车服务中。我们需要修改网关服务的配置

image.png

最后调整下模板页面中的静态资源的路径就可以了

image.png

然后启动服务访问即可

image.png

二、购物车功能

1.购物车模式处理

  讨论购物车中数据的存储方式。我们在购物车中可以有多见商品

image.png

然后对应的数据我们可以选择存储在Redis中,对应的数据存储结构我们要慎重的考虑,因为有多条记录,如果用List来存储

[{skuId:1,subTile:'华为',price:666},{skuId:1,subTile:'华为',price:666},{skuId:1,subTile:'华为',price:666}]

那么我们后面要对商品做添加删除和修改商品数量的时候就会比较麻烦,我们需要取出List中的整个数据,然后找到我们要操作的数据,然后把所有数据回写到Redis中,这种方式显然不可取,这时我们可以考虑hash的方式来存储:

image.png

这样我们就可以一条一条来处理了,相比上面会更加的灵活。然后我们在后端服务中存储的结构为

Map<String,Map<String,CartItemVo>>

2.购物车VO

  针对购物车的信息存储,我们创建两个对应的VO对象。

package com.msb.mall.vo;import java.math.BigDecimal;
import java.util.List;/*** 购物车中的商品信息*/
public class CartItem {// 商品的编号 SkuIdprivate Long skuId;// 商品的图片private String image;// 商品的标题private String title;// 是否选中private boolean check = true;// 商品的销售属性private List<String> skuAttr;// 商品的单价private BigDecimal price;// 购买的数量private Integer count;// 商品的总价private BigDecimal totalPrice;public Long getSkuId() {return skuId;}public void setSkuId(Long skuId) {this.skuId = skuId;}public String getImage() {return image;}public void setImage(String image) {this.image = image;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public boolean isCheck() {return check;}public void setCheck(boolean check) {this.check = check;}public List<String> getSkuAttr() {return skuAttr;}public void setSkuAttr(List<String> skuAttr) {this.skuAttr = skuAttr;}public BigDecimal getPrice() {return price;}public void setPrice(BigDecimal price) {this.price = price;}public Integer getCount() {return count;}public void setCount(Integer count) {this.count = count;}public BigDecimal getTotalPrice() {// 商品的总价  price * countreturn price.multiply(new BigDecimal(count));}}

Cart

package com.msb.mall.vo;import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;/*** 购物车*/
public class Cart {// 购物车中的商品种类private Integer countType;// 选中的商品数量private Integer checkCountNum;// 选中商品的总价private BigDecimal totalAmount;// 购物中存储的商品信息private List<CartItem> items;public Integer getCountType() {return items.size();}public Integer getCheckCountNum() {Integer count = 0;for (CartItem item : items) {if (item.isCheck()){count += item.getCount();}}return count;}public BigDecimal getTotalAmount() {BigDecimal amount = new BigDecimal(0);for (CartItem item : items) {if (item.isCheck()){amount = amount.add(item.getTotalPrice());}}return amount;}public List<CartItem> getItems() {return items;}public void setItems(List<CartItem> items) {this.items = items;}
}

3.认证信息

  我们需要在购物车服务中根据当前登录用的用户信息去Redis中查询对应的购物车信息。首先我们需要导入Redis的相关依赖,同时我们要借助于前面讲解的SpringSession来共享认证的Session信息。

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency>

添加属性文件信息

server.port=40000
spring.application.name=mall-cartspring.cloud.nacos.discovery.server-addr=192.168.56.100:8848
spring.thymeleaf.cache=falsespring.redis.host=192.168.56.100
spring.redis.port=6379
spring.thymeleaf.enabled=falsespring.session.store-type=redis
server.servlet.session.timeout=30m
spring.session.redis.namespace=spring:session

添加Cookie的配置信息

@Configuration
public class MySessionConfig {/*** 自定义Cookie的配置* @return*/@Beanpublic CookieSerializer cookieSerializer(){DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();cookieSerializer.setDomainName("msb.com"); // 设置session对应的一级域名cookieSerializer.setCookieName("msbsession");return cookieSerializer;}/*** 对存储在Redis中的数据指定序列化的方式* @return*/@Beanpublic RedisSerializer<Object> redisSerializer(){return new GenericJackson2JsonRedisSerializer();}
}

添加自定义的拦截器

/*** 我们自定义的拦截器:帮助我们获取当前登录的用户信息*     通过Session共享获取的*/
public class AuthInterceptor implements HandlerInterceptor {// 本地线程对象  Map<thread,Object>public static ThreadLocal<MemberVO> threadLocal = new ThreadLocal();@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 通过HttpSession获取当前登录的用户信息HttpSession session = request.getSession();Object attribute = session.getAttribute(AuthConstant.AUTH_SESSION_REDIS);if(attribute != null){MemberVO memberVO = (MemberVO) attribute;threadLocal.set(memberVO);}return true;}
}

注册拦截器

@Configuration
public class MyWebInterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/**");}
}

然后登录后访问controller服务测试

image.png

4.页面跳转

  从商品详情页面点击添加购物车完成添加购物车的逻辑。

image.png

5.添加购物车逻辑

  具体完成添加购物车的逻辑,也service中我们获取到商品的SKUId和商品数量后,我们要实现的逻辑

image.png

具体核心代码

/*** 把商品添加到购物车中* @param skuId* @param num* @return*/@Overridepublic CartItem addCart(Long skuId, Integer num) throws Exception {BoundHashOperations<String, Object, Object> hashOperations = getCartKeyOperation();// 如果Redis存储在商品的信息,那么我们只需要修改商品的数量就可以了Object o = hashOperations.get(skuId.toString());if(o != null){// 说明已经存在了这个商品那么修改商品的数量即可String json = (String) o;CartItem item = JSON.parseObject(json, CartItem.class);item.setCount(item.getCount()+num);hashOperations.put(skuId.toString(),JSON.toJSONString(item));return item;}CartItem item = new CartItem();CompletableFuture future1 = CompletableFuture.runAsync(()->{// 1.远程调用获取 商品信息R r = productFeignService.info(skuId);String skuInfoJSON = (String) r.get("skuInfoJSON");SkuInfoVo vo = JSON.parseObject(skuInfoJSON,SkuInfoVo.class);item.setCheck(true);item.setCount(num);item.setPrice(vo.getPrice());item.setImage(vo.getSkuDefaultImg());item.setSkuId(skuId);item.setTitle(vo.getSkuTitle());},executor);CompletableFuture future2 = CompletableFuture.runAsync(()->{// 2.获取商品的销售属性List<String> skuSaleAttrs = productFeignService.getSkuSaleAttrs(skuId);item.setSkuAttr(skuSaleAttrs);},executor);CompletableFuture.allOf(future1,future2).get();// 3.把数据存储在Redis中String json = JSON.toJSONString(item);hashOperations.put(skuId.toString(),json);return item;}private BoundHashOperations<String, Object, Object> getCartKeyOperation() {// hash key: cart:1   skuId:cartItemMemberVO memberVO = AuthInterceptor.threadLocal.get();String cartKey = CartConstant.CART_PERFIX + memberVO.getId();BoundHashOperations<String, Object, Object> hashOperations = redisTemplate.boundHashOps(cartKey);return hashOperations;}

6.购物车主页

  添加商品进入购物车后,我们可以点击结算进入购物车页面,那么我们需要在后台查询出所有的当前登录用户的购物车商品信息,然后在页面中展示

image.png

image.png

然后在页面中处理数据

image.png

image.png

相关文章:

【业务功能篇97】微服务-springcloud-springboot-电商购物车模块-获取当前登录用户的购物车信息

购物车功能 一、购物车模块 1.创建cart服务 我们需要先创建一个cart的微服务&#xff0c;然后添加相关的依赖&#xff0c;设置配置&#xff0c;放开注解。 <dependencies><dependency><groupId>com.msb.mall</groupId><artifactId>mall-commo…...

Shell常用的几个正则表达式:[:alnum:], [:alpha:], [:upper:], [:lower:], [:digit:] 认知

一&#xff1a;通配符命令简介&#xff1a; 匹配符合相关条件的符号&#xff0c;匹配文件名查找。 通配符类型&#xff1a; *&#xff1a;匹配任意长度的任意字符 &#xff1f;&#xff1a;匹配任意单个字符 []&#xff1a;匹配指定范围内的任意单个字符 [^]&#xff1a;匹配指…...

简单的爬虫代码 爬(豆瓣电影)

路漫漫其修远兮&#xff0c;吾将上下而求索 这次写一个最简单的python爬虫代码&#xff0c;也是大多教程第一次爬取的&#xff0c;代码里面有个别的简单介绍&#xff0c;希望能加深您对python爬虫的理解。 本次爬取两个网页数据 一 爬取的网站 豆瓣电影 爬取网页中的&#…...

微服务之架构演变

随着互联网的发展&#xff0c;网站应用规模不断扩大&#xff0c;网站架构随之不断演变&#xff0c;演变历史大致分为单体应用架构-垂直应用架构-分布式架构-SOA架构-微服务架构-云原生架构 架构演变 单体应用架构 以前网站流量小&#xff0c;只需要一个应用就可以把所有功能…...

面试问题记录一 --- C++(Qt方向)

以下是我于2023年6~7月间换工作时遇到的面试题目,有需要的小伙伴可以参考下。约100个题目。 1 C和C++的区别 1) 文件区别:C源文件后缀 .c;C++源文件后缀 .cpp 2) 返回值: C默认返回int型;C++ 若无返回值,必须指定为void 3) 参数列表:C默认接收多个…...

使用词袋模型(BoW)测试提取图像的特征点和聚类中心

文章目录 环境配置代码测试 环境配置 (1) 导入opencv&#xff0c;参考链接 https://blog.csdn.net/Aer_7z/article/details/132612369(2) 安装numpy 激活虚拟环境的前提下&#xff0c;输入&#xff1a; pip install numpy(3) 安装sklearn 激活虚拟环境的前提下&#xff0c;输…...

利用vba处理Excel表格数据实现键值转化,适用于将编码转化成对应的文本

最近遇到了一个甲方需要提供系统登录的用户名单和对应的角色权限内容。无奈直接从数据库导出的数据对应的都是编码&#xff0c;没有转成中文&#xff0c;想着偷个懒能不能直接用Excel直接转&#xff0c;网上看了一下有修改单元格格式的&#xff0c;但需要编码是2到3个。多的就用…...

IntelliJ IDEA(Windows 版)的所有快捷键

&#x1fa81;&#x1f341; 希望本文能够给您带来一定的帮助&#x1f338;文章粗浅&#xff0c;敬请批评指正&#xff01;&#x1f341;&#x1f425; 大家好 本文参考了 IntelliJ IDEA 的官网&#xff0c;列举了IntelliJ IDEA&#xff08;Windows 版&#xff09;的所有快捷…...

文件上传漏洞全面渗透姿势

0x00 文件上传场景 (本文档只做技术交流) 文件上传的场景真的随处可见&#xff0c;不加防范小心&#xff0c;容易造成漏洞&#xff0c;造成信息泄露&#xff0c;甚至更为严重的灾难。 比如某博客网站评论编辑模块&#xff0c;右上角就有支持上传图片的功能&#xff0c;提交带…...

GreenPlum的gpfdist使用与原理流程分析

一、简介 GreenPlum 的数据导入功能作为对数据源的一种扩充&#xff0c;数据导入的方式有&#xff1a; 1、insert 该方式通过 sql 语句&#xff0c;把数据一条一条插入至表中。这种方式&#xff0c;不仅读取数据慢&#xff08;一条一条读取&#xff09;&#xff0c;且数据需要…...

Spring AOP与静态代理/动态代理

文章目录 一、代理模式静态代理动态代理代理模式与AOP 二、Spring AOPSping AOP用来处理什么场景jdk 动态代理cglib 动态代理面试题&#xff1a;讲讲Spring AOP的原理与执行流程 总结 一、代理模式 代理模式是一种结构型设计模式&#xff0c;它允许对象提供替代品或占位符&…...

【LeetCode算法系列题解】第51~55题

CONTENTS LeetCode 51. N 皇后&#xff08;困难&#xff09;LeetCode 52. N 皇后 II&#xff08;困难&#xff09;LeetCode 53. 最大子序和&#xff08;中等&#xff09;LeetCode 54. 螺旋矩阵&#xff08;中等&#xff09;LeetCode 55. 跳跃游戏&#xff08;中等&#xff09; …...

驱动开发错误汇编

本博文将会不定期更新。以便记录我的驱动开发生涯中的一些点点滴滴的技术细节和琐事。 1. link阶段找不到导出函数 比如"LNK2019 无法解析的外部符号 _FltCreateCommunicationPort32"。 出现这种情况的原因是&#xff0c;驱动的编译环境忽略了所有的默认库&#x…...

知识图谱项目实践

目录 步骤 SpaCy Textacy——Text Analysis for Cybersecurity Networkx Dateparser 导入库 写出页面的名称 ​编辑 自然语言处理 词性标注 可能标记的完整列表 依存句法分析&#xff08;Dependency Parsing&#xff0c;DEP&#xff09; 可能的标签完整列表 实例理…...

stable diffusion实践操作-提示词-人物属性

系列文章目录 stable diffusion实践操作-提示词 文章目录 系列文章目录前言一、提示词汇总1.1 人物属性11.2 人物属性2 前言 本文主要收纳总结了提示词-人物属性。 一、提示词汇总 1.1 人物属性1 角色类型人物身材胸部头发-发型头发-发色[女仆][霊烏路空][大腿][乳房][呆毛…...

RabbitMQ的安装和配置

将RabbitMQ文件夹传到linux根目录 开启管理界面及配置...

WebRTC 日志

WebRTC 日志 flyfish WebRTC支持的日志等级 // // The meanings of the levels are: // LS_VERBOSE: This level is for data which we do not want to appear in the // normal debug log, but should appear in diagnostic logs. // LS_INFO: Chatty level used in de…...

【python爬虫】16.爬虫知识点总结复习

文章目录 前言爬虫总复习工具解析与提取&#xff08;一&#xff09;解析与提取&#xff08;二&#xff09;更厉害的请求存储更多的爬虫更强大的爬虫——框架给爬虫加上翅膀 爬虫进阶路线指引解析与提取 存储数据分析与可视化更多的爬虫更强大的爬虫——框架项目训练 反爬虫应对…...

Windows系统中Apache Http服务器简单使用

1 简介 Apache HTTP服务器是一个开源的、跨平台的Web服务器软件。它由Apache软件基金会开发和维护。Apache HTTP服务器可以在多种操作系统上运行&#xff0c;如Windows、Linux、Unix等&#xff0c;并且支持多种编程语言和技术&#xff0c;如PHP、Perl、Python、Java等。…...

Django ORM 框架中的表关系,你真的弄懂了吗?

Django ORM 框架中的表关系 为了说清楚问题&#xff0c;我们设计一个 crm 系统&#xff0c;包含五张表&#xff1a; 1.tb_student 学生表 2.tb_student_detail 学生详情表 3.tb_salesman 课程顾问表 4.tb_course 课程表 5.tb_entry 报名表 表关系和字段如下图&#xff1a…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...