苍穹外卖-DAY07
苍穹外卖-DAY07
一、redis缓存
设置缓存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public Result<List<DishVO>> list(Long categoryId) {
//构造redis中key
String Key = "dish_"+categoryId;
//获取redis中数据
List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(Key);
//如果存在直接返回
if(list != null && list.size() != 0){
return Result.success(list);
}
Dish dish = new Dish();
dish.setCategoryId(categoryId);
dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品
list = dishService.listWithFlavor(dish);
//不存在设置数据返回
redisTemplate.opsForValue().set(Key,list);
return Result.success(list);
}删除缓存
1
2
3
4
5
6private void deleteCache(String patten){
Set keys = redisTemplate.keys(patten);
redisTemplate.delete(keys);
}
二、SpringCache
具体实现流程

具体方法

1.@CachePut
1 | // 修改完数据库后,自动把最新的 Dish 对象塞回 Redis,覆盖旧数据 |
SPEL 表达式
Spring Expression Language (SpEL) 允许在注解中通过字符串的形式,动态获取方法参数或返回值的属性
在 Redis 缓存注解(@Cacheable, @CachePut)中,我们用它来定义 Key
- 获取参数属性:
#参数名.属性名:例如#dish.id(推荐,语义清晰)#p0.id、#a0.id:表示第1个参数的 id 属性(p=param, a=arg)。
- 获取返回值(仅限
@CachePut):#result:代表方法执行后的返回值。- 场景:新增数据时,ID 可能是数据库自动生成的,参数里没有 ID。这时必须用
#result.id才能拿到 ID 存入缓存。
- 拼接字符串:
- 单引号包裹字符串:
'user_' + #id
- 单引号包裹字符串:
- 具体如下
redis 中key的树形存储方式
Redis 本质上是一个 Key-Value 数据库,并没有真正的“文件夹”概念。但是,所有的 Redis 可视化管理工具(如 Another Redis Desktop Manager, RDM)都遵循一个约定:
约定:使用冒号 : 作为分隔符来模拟目录结构

2.@Cacheable
1 |
|
执行流程
当你调用一个被它标记的方法时,Spring 会按以下步骤操作:
- 先查缓存:根据定义的 Key,去
Redis(或其他缓存)里找有没有数据。 - 如果命中:
- 直接返回缓存里的数据。
- 完全跳过你的 Java 方法体(里面的
SQL语句压根不会执行)。
- 如果未命中:
- 执行你的 Java 方法(去查数据库)。
- 拿到返回值。
- 自动写入缓存(为下一次请求做准备)。
- 返回数据给调用者。
表达式限制
@CachePut 不同:
@CachePut:方法肯定会执行,所以它的 Key 可以使用#result(返回值)来生成。@Cacheable:因为要先查缓存,还没执行方法呢,哪里来的返回值?- 结论:
@Cacheable的key属性中不能使用#result,只能使用参数(如#id,#p0)。
- 结论:
底层原理
在 Controller 里注入 DishService 时:
1 | @Autowired |
Spring 容器并没有直接把 DishService 原始对象,而是给了你一个 代理对象(Proxy)。这个代理对象“包裹”了你的原始对象。
Spring 在运行时动态生成的代理类大概长这样(简化版):
1 | public class DishServiceProxy extends DishService { |
3.@CacheEvict
根据 ID 删除某一条或多条数据。
1 |
|
1 | // 只要执行这个方法,dishCache 下的所有 Key 全部被清空! |
底层原理依旧是通过动态代理实现
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 十七.!