SpringCache
针对不同的缓存技术需要实现不同的CacheManager:
在spring boot项目中,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存支持即可。
@CachePut注解
@CachePut 说明:
作用: 将方法返回值,放入缓存
value: 缓存的名称, 每个缓存名称下面可以有很多key
key: 缓存的key ----------> 支持Spring的表达式语言SPEL语法
在save方法上加上注解 @CachePut
@CachePut(value = "userCache",key = "#user.id")@PostMappingpublic User save(User user){userService.save(user);return user;}
key的写法如下:
#user.id : #user指的是方法形参的名称, id指的是user的id属性 , 也就是使用user的id属性作为key ;
#user.name: #user指的是方法形参的名称, name指的是user的name属性 ,也就是使用user的name属性作为key ;
#result.id : #result代表方法返回值,该表达式 代表以返回对象的id属性作为key ;
#result.name : #result代表方法返回值,该表达式 代表以返回对象的name属性作为key ;
@CacheEvict注解
@CacheEvict 说明:
作用: 清理指定缓存
value: 缓存的名称,每个缓存名称下面可以有多个key
key: 缓存的key ----------> 支持Spring的表达式语言SPEL语法
在 update 方法上加注解@CacheEvict
//@CacheEvict(value = "userCache",key = "#p0.id") //第一个参数的id属性//@CacheEvict(value = "userCache",key = "#user.id") //参数名为user参数的id属性//@CacheEvict(value = "userCache",key = "#root.args[0].id") //第一个参数的id属性@CacheEvict(value = "userCache",key = "#result.id") //返回值的id属性@PutMappingpublic User update(User user){userService.updateById(user);return user;}
@Cacheable注解
@Cacheable 说明:
作用: 在方法执行前,spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
value: 缓存的名称,每个缓存名称下面可以有多个key
key: 缓存的key ----------> 支持Spring的表达式语言SPEL语法
缓存非null值
在@Cacheable注解中,提供了两个属性分别为: condition, unless 。
condition : 表示满足什么条件, 再进行缓存
unless : 表示满足条件则不缓存 ; 与上述的condition是反向的
/*** Cacheable:在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中* value:缓存的名称,每个缓存名称下面可以有多个key* key:缓存的key* condition:条件,满足条件时才缓存数据* unless:满足条件则不缓存*/@Cacheable(value = "userCache",key = "#id",unless = "#result == null")@GetMapping("/{id}")public User getById(@PathVariable Long id){User user = userService.getById(id);return user;}
在list方法上加注解@Cacheable
@Cacheable(value = "userCache", key = "#user.id + '_' + #user.name")@GetMapping("/list")public List<User> list(User user){LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(user.getId() != null,User::getId,user.getId());queryWrapper.eq(user.getName() != null,User::getName,user.getName());List<User> list = userService.list(queryWrapper);return list;}
key = "#user.id + '_' + #user.name"
这种 key 的构造方式是可以自定义的,并不是固定的。这里采用了 user.id
和 user.name
组合成缓存 key 的方式,主要目的是为了唯一标识这个查询,确保缓存数据的准确性。你可以根据业务需求来构造不同的 key。
在实际开发中,统一 key 的定义方式有助于团队协作和代码维护,但具体的 key 内容和格式可以灵活调整。关键是要保证构造的 key 能唯一且清晰地标识对应的数据。一般来说,开发中会根据查询条件、业务逻辑、数据结构等因素来设计 key,而不是固定一种形式。