缓存通常用来加快数据库中经常要使用的数据。大部分情况下我们使用 redis 来缓存 MySQL 数据库的热点数据。
EnableCaching#
在 spring boot 中使用缓存还是比较简单的
首先添加依赖
<!-- cache 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
在启动类开启缓存支持
@SpringBootApplication
@EnableCaching
在配置文件中指定使用 redis 缓存,如果不指定则使用 jvm 内存
在使用 redis 做缓存之前,需要正确的配置 redis 的连接信息
#cacheing
spring.cache.type=redis
#指定前缀
#spring.cache.redis.key-prefix=test
#指定存活时长
#spring.cache.redis.time-to-live= 1d
最后在 redis 的配置类中增加 @EnableCaching
注解和 缓存管理器
/**
* 申明缓存管理器,会创建一个切面(aspect)并触发Spring缓存注解的切点(pointcut)
* 根据类或者方法所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,将数据添加到缓存之中或者从缓存中移除某个值
*
* @return
*/
@Bean
@SuppressWarnings("all")
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(1))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
缓存注解#
缓存注解 | 解释 |
---|---|
@EnableCaching | 开启缓存注解的支持 |
@CacheConfig | 用于统一制定一些配置参数,这样在其他缓存注解里面就不用重复指定 |
@Cacheable | 如果之前已经有缓存数据值直接返回缓存数据,否则执行方法,缓存方法的返回结果 |
@CachePut | 能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用 |
@CacheEvict | 能够根据一定的条件对缓存进行清空 |
@Caching | 组合多个 Cache 注解的使用 |
@CacheConfig#
此注解常用来配置统一的缓存参数
// 在controller中使用此注解用来指定缓存的名字,类似于前缀
@CacheConfig(cacheNames = "test")
@Cacheable#
此注解常用于查询方法中,使用此注解后会先从缓存中查,如果缓存中没有,再从数据库中查,并把查询出的结果放入缓存中。
Mermaid Loading...
// 如果配置了@CacheConfig的全局cacheName/value 则这里面的可以省略
@Cacheable(value = "test", key = "methodName")
// @Cacheable支持el表达式
@Cacheable(key = "methodName + ':' + #p0 + ':' + #p1")
public Result<Object> getSubordinateAddress(String province,String city){}
@Cacheable(value="users", key="#user.id")
public User find(User user) {}
key
支持的属性列表如下
属性名称 | 描述 | 示例 |
---|---|---|
methodName | 当前方法名 | #root.methodName |
method | 当前方法 | #root.method.name |
target | 当前被调用的对象 | #root.target |
targetClass | 当前被调用的对象的 class | #root.targetClass |
args | 当前方法参数组成的数组 | #root.args[0] |
caches | 当前被调用的方法使用的 Cache | #root.caches[0].name |
@CachePut#
此注解常用来更新缓存。它会忽略缓存中的值,而是始终执行方法。
执行顺序为 调用方法 ---> 获取结果 ---> 更新缓存
Mermaid Loading...
@CachePut(value = "myCache", key = "#entity.id")
public void saveEntity(MyEntity entity) {
repository.save(entity);
}
@CacheEvict#
此注解用来删除对应的缓存。
@CacheEvict(value = "myCache", key = "#id")
public void deleteEntityById(Long id) {
repository.deleteById(id);
}
在使用 allEntries=true
时,会忽略 key,删除指定 cacheName/value 中的全部值。
你也可以使用 cacheMange 对象来删除指定的缓存,以下代码表示当 test 缓存不为空时,将其清空
Objects.requireNonNull(restTemplateConfig.cacheManager(null).getCache("test")).clear();
@Caching#
此注解用来组合多个上面的缓存注解进行使用
@Caching(
cacheable = {
@Cacheable(value = "myCache", key = "#id")
},
evict = {
@CacheEvict(value = "otherCache", key = "#id")
}
)
public MyEntity getEntityById(Long id) {
return repository.findById(id).orElse(null);
}
调用顺序如下
Mermaid Loading...
SpringBoot 项目中使用缓存 Cache 的正确姿势!!!
SpringBoot 缓存管理 @EnableCaching、@Cacheable