Day07-苍穹外卖(spring-cache以及购物车篇)

前言:

今天写第七天的内容,主要介绍一下spring-cache,还有自己的一些问题,思考,踩坑点

今日所学:

  • 缓存菜品
  • spring-cache介绍以及应用
  • 增删购物车

目录

1.缓存菜品

问题:

实现思路:

核心代码:

2. spring-cache介绍以及应用

2.1 介绍

2.2 EnableCaching

作用:

2.3 Cacheput

作用:

2.4 Cacheable

作用:

底层:

2.5 CacheEvict

作用:

思考:

2.6 spring-cache应用

3.增删购物车

3.1 增加购物车

问题:

解决思路:

核心代码

3.2 查看/清空购物车

注意点:

3.3 删除一条购物车(补充)

解决思路:

3.4 思考


1.缓存菜品

问题:

如何缓存菜品至redis,以此降低对mysql的访问量

实现思路:

核心代码:

这里以user包下的DishController类的list方法为例,进行说明

第一步我们动态构造key(确保每个分类缓存的key不同),接着实现过程就跟实现思路那张图所描绘的一致了。我们先是查询redis是否有改类菜品数据,如果有,直接返回redis的菜品数据即可。如果没有,在从mysql进行查询,并把数据存入到redis中

2. spring-cache介绍以及应用

2.1 介绍

Spring Cache 是 Spring 框架提供的一个缓存抽象层,旨在简化在应用程序中使用缓存的过程。它通过注解的方式,允许开发者在不修改业务逻辑代码的情况下,轻松地添加缓存功能。Spring Cache 支持多种缓存实现,如 EhCache、Guava、Caffeine 等,并且可以与 Spring 的其他功能无缝集成。

上面阿巴阿巴说了这么多,其实我们不用关心。

我们只需要记住这玩意跟事务(@Transactional)类似,基于注解实现,也就是简单一个注解,就能实现缓存功能

下面介绍下spring-cache常用的几个方法

2.2 EnableCaching

作用:

启动类上开启缓存注解功能(别忘了!!)

2.3 Cacheput

作用:

方法的返回值放到缓存中(方法的返回值画重点)

key键的生成规则: 

如果使用spring_cache缓存数据,key键的生成:usercache::key(key由#加方法的参数名决定)

2.4 Cacheable

作用:

方法执行前查询缓存中是否有数据,如果有数据,则直接返回缓存数据,如果没有缓存数据,调用方法并将方法返回值放到缓存中(就我们上面缓存菜品举例的那个功能)

key键的查询规则:

查询是否存在usercache::id的key,存在直接返回数据(不用执行方法),不存在在调用方法

这里cacheable和cacheput的cacheNames最好保持一致(要确保生成的key和查询的key是一致的)

底层:

使用代理技术(类似于AOP),先进行缓存的查询,再执行getById方法

就是我们上面举例的那个缓存菜品功能封装成一个注解了(可以这样理解,真实执行getById方法用的是反射)

2.5 CacheEvict

作用:

将一条或多条数据从缓存中删除

下面是清理一条缓存数据

也很容易看懂,精确key键就行了

再下面这个是清理所有缓存数据的

思考:

如果是清理多条数据呢

感兴趣的可以问下你的deepseek,这里不展开

2.6 spring-cache应用

具体操作是在admin和user端的setmealController

这里我着重讲下为什么admin端新增套餐要删除原有缓存数据

有人肯定不理解,新增套餐不应该是添加缓存数据,每个套餐生成的key值都是不同的,不会覆盖原有key值,为什么不用@Cacheput。这里我建议在仔细看下@Cacheput的功能:

方法的返回值放到缓存中

这个方法的返回值是什么呢?是Result(空空如也的那种)

知道这个后,我们再讲下为什么使用@CacheEvict

这里主要是为了及时更新同一类别下套餐的数量,我们知道套餐和类别是n : 1的关系(感兴趣的可以看下我上条博客,有表之间的E-R图),在user端当我们第一次根据类别id查询套餐的时候,已经把同一类别所有的套餐都加入缓存了(@Cacheable的功能)

而回到admin端,我们在数据库里给当前类别新增了一个套餐后,并没有同步到cache里,

导致users端一直是查询cache里的旧数据(也是@Cacheable的功能),所以加入新套餐后,要清空当前类别的缓存,让user端查找时重新加入

3.增删购物车

3.1 增加购物车

问题:

如何添加购物车商品

解决思路:

跟其他添加操作的功能接口一样,其实也就是数据从controller层传入,经过service层的逻辑处理,传到mapper层储存到相应的数据库中(这里是shopping_cart库)

但是这个功能接口的难点在于:

  1. 要判断是否这次添加的是否是相同的菜品或者是套餐,是的话Amount+1即可
  2. 要判断添加的是菜品还是套餐,因为他们两添加的字段并不一样

确定了这两点,剩下的就是很平常的insert操作

核心代码

(这里仅展示service层的代码)

1.判断添加的是否是相同的菜品或者是套餐

这里注意userId由ThreadLocal获得(老朋友了,用处是动态获取id),Mapper.list映射的是select的动态SQL,查找是否有该商品,找到了,数量加一,再进行数据库更新即可

2.判断添加的是菜品还是套餐

判断方法很简单,获取shoppingCart.getDishId()或者是getsetmealId()的值,哪个不为空,就添加哪个

另外说一下,这里id是自增生成的,user_id是由ThreadLocal传入的,dish_id或setmeal_id跟dish_flavor(如果是传入的dish_id)都是前端传入的。所以我们只需要再设置name,image,amount,number,createTime的值就行了。

最后插入该数据

3.2 查看/清空购物车

非常简单的操作,这里仅说下注意点

注意点:

这里注意购物车的区分是由userId(查看同一用户的购物车,清空同一用户的购物车)确定的(不是由id),查询前要先插入userId的值,作为where查询的条件

下面的清空购物车也是按照也是依据userId来删除的

3.3 删除一条购物车(补充)

这个课程中没有涉及,但是接口文档中有,就顺带给做了,感兴趣的可以看一看

解决思路:

逻辑跟添加购物车是一样的(甚至简单点),先判断是否存在这条数据,存在的话判断num数量是否是大于零,大于零的话数量减一(后面记得更新),当num==0时,删除这一条数据

这边注意下先判断大于零再number-1,这边设计表的时候number没有加约束,给我干道-30来了。

金额更是成了负数(用户狂喜)

3.4 思考

我们能否用redis来储存这些商城数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值