一、概述
Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
Spring Cache 提供了一层抽象,底层可以切换不同的缓存实现,例如:
-
EHCache
-
Caffeine
-
Redis(常用)
二、环境准备
1、导入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>
已导入,无需再次导入
2、添加配置支持
在application.yml文件中添加redis的支持
spring:
redis:
host: 127.0.0.1
port: 6379
password: 123456
已创建,无需再次创建
三、常用注解
在SpringCache中提供了很多缓存操作的注解,常见的是以下几个:
注解 | 说明 |
@EnableCaching | 开启缓存注解功能,通常加在启动类上 |
@Cacheable | 在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,调用方法并将方法返回值放到缓存中 |
@CachePut | 将方法的返回值放到缓存中 |
@CacheEvict | 将一条或多条数据从缓存中删除 |
@Caching | 缓存的结合体,可以组合以上注解在一个方法中使用,比如有新增,有删除 |
在spring boot项目中,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存支持即可。
1、@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中,冒号通常用作键的命名约定,可以创建层次结构,类似于文件系统中的路径结构,提升查找效率
其中在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"
2、@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
3、@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();
}
4、@Caching
作用: 组装其他缓存注解
-
cacheable 组装一个或多个@Cacheable注解
-
put 组装一个或多个@CachePut注解
-
evict 组装一个或多个@CacheEvict注解
@Caching(
cacheable = {
@Cacheable(value = "userCache",key = "#id")
},
put = {
@CachePut(value = "userCache",key = "#result.name"),
@CachePut(value = "userCache",key = "#result.age")
}
)
public User insert(User user){
userMapper.insert(user);
return user;
}
四、缓存解决权限接口响应慢的问题
1、项目中集成Spring Cache
-
先导入Spring Data Redis起步依赖和Spring Cacha起步依赖
在zzyl-common模块中新增依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
-
在application.yml文件中添加Redis相关的配置
spring:
redis:
host: 127.0.0.1
port: 6379
password: 123456
2、资源管理模块集成Spring Cache
缓存同步的思路:
-
查询的时候添加到缓存中
-
增删改的时候,删除缓存
@Service
@Transactional
public class ResourceServiceImpl implements ResourceService {
/**
* 多条件列表查询
* @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) {
}
}
上述代码中使用到的常量需要自己定义:
package com.zzyl.constant;
public class CacheConstant {
/**
* 缓存父包
*/
public static final String RESOURCE_PREFIX= "resource:";
public static final String RESOURCE_LIST = RESOURCE_PREFIX+"list";
public static final String RESOURCE_TREE = RESOURCE_PREFIX+"tree";
}
其中ResourceDto 需要添加根据查询条件获取hashCode方法
@Override
public int hashCode() {
int result = Objects.hash(super.hashCode(), getParentResourceNo(), getResourceType(),getDataState());
return result;
}
标签:缓存,RESOURCE,Spring,Cache,value,id,key,public
From: https://blog.csdn.net/susjj663/article/details/140364412