一、概述
Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
Spring Cache 提供了一层抽象,底层可以切换不同的缓存实现,例如:
- EHCache
- Caffeine
- Redis(常用)
二、环境准备
准备一个Springboot项目
导入Redis和SpringCache依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
添加配置支持
在application.yml文件中添加redis的支持
spring:
redis:
host: 127.0.0.1
port: 6379
password: 123456
常用注解
在SpringCache中提供了很多缓存操作的注解,常见的是以下几个:
在spring boot项目中,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存支持即可。
三、@Cacheable
在方法执行前,spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中,查询的时候使用
@Cacheable(cacheNames = "userCache",key="#id")
public User getById(Long id){
User user = userMapper.getById(id);
if(user == null){
throw new RuntimeException("用户不存在");
}
return user;
}
存储到redis之后的数据是这样的
- cacheNames = “userCache” : 表示命名空间,key的第一层级
- key=“#id” : id指的是查询的参数, 也就是使用id属性作为key
- 在Redis中,冒号通常用作键的命名约定,可以创建层次结构,类似于文件系统中的路径结构,提升查找效率
多条件查询使用Cacheable,比如查询的方法参数有多个,我们可以使用hashcode作为缓存的key,如下代码
@Cacheable(value = "userCache",key="#userDto.hashCode()",unless = "#result.size() == 0")
public List<User> getList(UserDto userDto){
List<User> list = userMapper.getList("%" + userDto.getName() + "%", userDto.getAge());
return list;
}
在UserDto 中需要提供一个hashCode方法
@Data
public class UserDto {
private String name;
private int age;
@Override
public int hashCode() {
int result = Objects.hash(getName(),getAge());
return result;
}
}
hashcode的特点是,只要参数相同,则生成后的hashcode值肯定相同
如果返回结果为空,则不缓存unless="#result == null"或unless="#result.size()==0"
四、@CachePut
作用: 将方法返回值,放入缓存,一般保存的时候使用该注解
@CachePut(value = "userCache", key = "#user.id")//key的生成:userCache::1
public User insert(User user){
userMapper.insert(user);
return user;
}
#user.id : #user指的是方法形参的名称, id指的是user的id属性 , 也就是使用user的id属性作为key
五、@CacheEvict
作用: 清理指定缓存
@CacheEvict(cacheNames = "userCache",key = "#id")//删除某个key对应的缓存数据
public void deleteById(Long id){
userMapper.deleteById(id);
}
@CacheEvict(cacheNames = "userCache",allEntries = true)//删除userCache下所有的缓存数据
public void deleteAll(){
userMapper.deleteAll();
}
六、@Caching
作用: 组装其他缓存注解
- cacheable 组装一个或多个@Cacheable注解
- put 组装一个或多个@CachePut注解
- evict 组装一个或多个@CacheEvict注解
@Caching( evict = { @CacheEvict(cacheNames = "userCache",allEntries = true),
@CacheEvict(cacheNames = "userList",allEntries = true)
})
public void deleteAll(){
userMapper.deleteAll();
}
总结
/**
* 多条件列表查询
* @param resourceDto
* @return
*/
@Cacheable(value = CacheConstant.RESOURCE_LIST ,key ="#resourceDto.hashCode()")
@Override
public List<ResourceVo> getList(ResourceDto resourceDto) {
方法略...
}
/**
* 封装资源的树形结构
*
* @param resourceDto
* @return
*/
@Cacheable(value = CacheConstant.RESOURCE_TREE )
@Override
public TreeVo resourceTreeVo(ResourceDto resourceDto) {
方法略...
}
/**
* 添加资源
* @param resourceDto
*/
@Caching(evict = {@CacheEvict(value = CacheConstant.RESOURCE_LIST ,allEntries = true),
@CacheEvict(value = CacheConstant.RESOURCE_TREE ,allEntries = true)})
@Override
public void createResource(ResourceDto resourceDto) {
方法略...
}
/**
* 修改资源
* @param resourceDto
*/
@Caching(evict = {@CacheEvict(value = CacheConstant.RESOURCE_LIST ,allEntries = true),
@CacheEvict(value = CacheConstant.RESOURCE_TREE ,allEntries = true)})
@Override
public void updateResource(ResourceDto resourceDto) {
}
/**
* 启用禁用
* @param resourceVo
* @return
*/
@Caching(evict = {@CacheEvict(value = CacheConstant.RESOURCE_LIST ,allEntries = true),
@CacheEvict(value = CacheConstant.RESOURCE_TREE ,allEntries = true)})
@Override
public void isEnable(ResourceVo resourceVo) {
}
/**
* 删除菜单
* @param resourceNo
*/
@Caching(evict = {@CacheEvict(value = CacheConstant.RESOURCE_LIST ,allEntries = true),
@CacheEvict(value = CacheConstant.RESOURCE_TREE ,allEntries = true)})
@Override
public void deleteByResourceNo(String resourceNo) {
}
一般查询需要添加缓存,删除修改和新增都是要先删除缓存的。