电商项目——全文检索-ElasticSearch——第一章——中篇
电商项目——商城业务-商品上架——第二章——中篇
电商项目——商城业务-首页——第三章——中篇
电商项目——性能压测——第四章——中篇
电商项目——缓存——第五章——中篇
电商项目——商城业务-检索服务——第六章——中篇
电商项目——商城业务-异步——第七章——中篇
电商项目——商品详情——第八章——中篇
电商项目——认证服务——第九章——中篇
电商项目——购物车——第十章——中篇
电商项目——消息队列——第十一章——中篇
电商项目——订单服务——第十二章——中篇
电商项目——分布式事务——第十三章——中篇
文章目录
1:环境搭建
我们先来搭建好购物车的环境
第一步:创建一个购物车微服务,并且配置好域名,映射到我们的linux虚拟机,并编写好配置文件
spring:
application:
name: mall-cart
cloud:
nacos:
discovery:
server-addr: localhost:8848
thymeleaf:
cache: false
server:
port: 12000
第二步:使用nginx实现动静分离,并且配置好网关
网关新增配置
- id: mall_cart_route
uri: lb://mall-cart
predicates:
- Host=cart.mall.com
第三步测试:
2:数据模型分析
我们没登录的时候相当于一个临时商品,只要我们登录了以后,我们会将临时商品一起加到我们登录的用户里面的购物车里面
-
登录购物车:登录以后,会将临时购物车的数据全部合并过来,并清空临时购物车
-
离线购物车:浏览器即使关闭,下次进入,临时购物车数据都在
-
购物车(mall-cart)要完成的操作
-
购物车( mall-cart)要怎么存储数据??
登录购物车:用户只要一登录了,购物车里面的商品都是永久存储的,我们会使用mysql;我们在仔细一分析,购物车(mall-cart)它是读多,写多的高并发操作,所以我们如果使用了数据库,很容易让数据库承担非常大的压力,mongodb也不好用;所以我们可以使用redis(有极高的读写并发能力),但是又会有一个问题,我们购物车里面的数据是永久保存,可是我们的redis是存在内存里的,一旦宕机,购物车里的商品就全没有了;这个问题redis也帮我们解决了:在安装好redis的时候,它有一个持久化解决的策略,让redis的每一条数据都可以持久化到mysql数据库里面(虽然会损失一些性能,但是还是比mysql强)
临时购物车:我们也可以放在redis里面存储,临时购物车里面的数据可以存放很多地方,比如,LocalStorage(客户端存储):只要是我们的购物车数据都可以存储在浏览器自带的LocalStorage,除非浏览器卸载,否则数据一直都会存在,,它的优点就是减轻了后端的压力,缺点就是在大数据的时代下,每一个人推荐的首页都不一样,它就是通过我们存放在购物车里面的数据,来进行首页推荐;如果我们把数据都放在浏览器端,我们的后端就没法进行大数据分析,无法进行首页推荐
-
总结:离线/在线购物车都把所有的数据都存放在redis里面
-
我们现在就要分析购物车的结构,知道我们以后要怎么进行增删改查
3:VO编写
通过上一节,我们分析的存储购物车数据的结构,我们来封装一个vo
CartItem
**
* @author Mr.zhneg
* @create 2020-11-15-15:06
* 购物项内容
* 因为我们要自己定义totalPrice的getter,setter所以我们要注释掉@Data
*/
//@Data
public class CartItem {
private Long skuId;
private Boolean check=true;
private String title;
private String image;
private List<String> skuAttr;
private BigDecimal price;
private Integer count;
private BigDecimal totalPrice;
//...
/**
* 计算购物项总价
* @return
*/
public BigDecimal getTotalPrice() {
BigDecimal multiply = this.price.multiply(new BigDecimal("" + this.count));
return multiply;
}
}
/**
* @author Mr.zhneg
* @create 2020-11-15-15:04
* 整个购物车
* 需要计算属性,必须要重写它的get方法,保证每次获取属性都会进行计算
*/
@Data
public class Cart {
List<CartItem> items;
private Integer countNum;//商品数量
private Integer countType;//商品类型数量
private BigDecimal totalAmount;//商品总价
private BigDecimal reduce=new BigDecimal(0);//减免价格
public List<CartItem> getItems() {
return items;
}
public void setItems(List<CartItem> items) {
this.items = items;
}
public Integer getCountNum() {
int count=0;
if (items!=null&&items.size()>0){
for (CartItem cart:items
) {
count+=cart.getCount();
}
}
return count;
}
public Integer getCountType() {
int count=0;
if (items!=null&&items.size()>0){
for (CartItem cart:items
) {
count+=1;
}
}
return count;
}
public BigDecimal getTotalAmount() {
BigDecimal amount=new BigDecimal("0");
//计算购物项总价
if (items!=null&&items.size()>0){
for (CartItem cart:items
) {
BigDecimal totalPrice=cart.getTotalPrice();
amount=amount.add(totalPrice);
}
}
//2:减去优惠价
BigDecimal subtract = amount.subtract(getReduce());
return subtract;
}
public BigDecimal getReduce() {
return reduce;
}
public void setReduce(BigDecimal reduce) {
this.reduce = reduce;
}
}
4:ThreadLocal用户身份鉴别
我们先在mall-cart中配置相关的redis依赖,和写一个service
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring:
redis:
host: 192.168.56.10
第二步:编写CartServiceImpl的逻辑层
第一个问题:我们要看自己到底有没有登录??
整合SpringSession
- 引入依赖
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
- 导入配置文件,并且复制一份MallSessionConfig到mall-cart中
spring:
session:
store-type: redis
MallSessionConfig
@Configuration
public class MallSessionConfig {
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("MALLSESSION");
serializer.setDomainName("mall.com");
return serializer;
}
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
return new GenericJackson2JsonRedisSer