SpringBoot--Spring Boot原生缓存基于Redis的Cacheable注解使用
文章目录
- [SpringBoot--Spring Boot原生缓存基于Redis的Cacheable注解使用](#SpringBoot--Spring Boot原生缓存基于Redis的Cacheable注解使用)
-
- 概述
- [1. 基础配置](#1. 基础配置)
-
- [1.1 添加依赖](#1.1 添加依赖)
- [1.2 配置文件](#1.2 配置文件)
- [1.3 序列化配置](#1.3 序列化配置)
- [2. 缓存注解使用](#2. 缓存注解使用)
-
- [2.1 @Cacheable - 缓存查询](#2.1 @Cacheable - 缓存查询)
- [2.2 @CacheEvict - 缓存清除](#2.2 @CacheEvict - 缓存清除)
- [3. 自定义TTL管理](#3. 自定义TTL管理)
-
- [3.1 自定义缓存管理器](#3.1 自定义缓存管理器)
- [3.2 缓存配置类](#3.2 缓存配置类)
- [3.3 不同TTL的缓存使用](#3.3 不同TTL的缓存使用)
- [4. 关键注意事项](#4. 关键注意事项)
-
- [4.1 配置冲突解决](#4.1 配置冲突解决)
- [4.2 缓存键生成规则](#4.2 缓存键生成规则)
- [4.3 TTL优先级](#4.3 TTL优先级)
- [4.4 空值缓存策略](#4.4 空值缓存策略)
- [4.5 最佳实践](#4.5 最佳实践)
概述
Spring Boot 通过 @Cacheable 和 @CacheEvict 注解简化了 Redis 缓存的使用,提供了声明式的缓存管理方案。
1. 基础配置
1.1 添加依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
1.2 配置文件
yml
spring:
redis:
host: 127.0.0.1
port: 6379
password: 123456
database: 1
cache:
type: redis
redis:
cache-null-values: false # 不缓存null值
time-to-live: 9000ms # 默认过期时间
use-key-prefix: true # 使用key前缀
1.3 序列化配置
java
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用Jackson序列化
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
return template;
}
}
2. 缓存注解使用
2.1 @Cacheable - 缓存查询
-
参数说明
-
value ="bills":缓存名称,在 Redis 中作为前缀
-
key ="#id":缓存键,使用方法的 id 参数
-
java
@Service
public class BillService {
/**
* 查询账单并缓存结果
* value: 缓存名称(Redis中的前缀)
* key: 缓存键,使用SpEL表达式
*/
@Cacheable(value = "bills", key = "#id")
public ResultJSON findBillById(Integer id) {
// 只有缓存不存在时才会执行此方法
return ResultJSON.ok(this.getById(id));
}
}
- 工作机制:
- 检查缓存中是否存在键为
bills::[id]的数据 - 存在:直接返回缓存数据,不执行方法
- 不存在:执行方法,将结果存入缓存
2.2 @CacheEvict - 缓存清除
-
参数说明
-
value ="bills":缓存名称,与 @Cacheable 中的一致
-
key ="#id":缓存键,使用方法的 id 参数
-
java
@CacheEvict(value = "bills", key = "#id")
public ResultJSON deleteBill(Integer id) {
// 方法执行成功后,自动删除对应的缓存
return ResultJSON.ok(this.removeById(id));
}
清除所有缓存
java
@CacheEvict(value = "bills", allEntries = true)
public ResultJSON clearAllBills() {
// 清除bills缓存区域的所有数据
return ResultJSON.ok("所有账单缓存已清除");
}
3. 自定义TTL管理
3.1 自定义缓存管理器
java
public class MyRedisCacheManager extends RedisCacheManager {
public MyRedisCacheManager(RedisCacheWriter cacheWriter,
RedisCacheConfiguration defaultCacheConfiguration) {
super(cacheWriter, defaultCacheConfiguration);
}
@Override
protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
// 解析缓存名称中的TTL配置,格式:cacheName#ttlSeconds
String[] array = StringUtils.delimitedListToStringArray(name, "#");
name = array[0];
if (array.length > 1) {
long ttl = Long.parseLong(array[1]);
cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl));
}
return super.createRedisCache(name, cacheConfig);
}
}
3.2 缓存配置类
java
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
@Value("${spring.redis.host}")
private String hostName;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.port}")
private Integer port;
@Value("${spring.redis.database}")
private int database;
@Bean
public CacheManager cacheManager() {
// 默认缓存配置(1天过期)
RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration
.defaultCacheConfig()
.entryTtl(Duration.ofDays(1))
.computePrefixWith(cacheName -> "caching:" + cacheName);
return new MyRedisCacheManager(
RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory()),
defaultCacheConfig
);
}
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(hostName);
config.setPort(port);
config.setDatabase(database);
config.setPassword(RedisPassword.of(password));
// configuration.setHostName("127.0.0.1");
// configuration.setPort(6379);
// configuration.setDatabase(0);
// configuration.setPassword("123456"); // 密码
return new LettuceConnectionFactory(config);
}
}
3.3 不同TTL的缓存使用
java
@Service
public class BillService {
// 3600秒过期
@Cacheable(cacheNames = "billCache#3600", key = "#id")
public ResultJSON findBillById(Integer id) {
return ResultJSON.ok(this.getById(id));
}
// 4800秒过期
@Cacheable(cacheNames = "providerCache#4800", key = "#id")
public ResultJSON getProviderById(Integer id) {
return ResultJSON.ok(this.getById(id));
}
// 清除指定缓存(需要匹配TTL配置)
@CacheEvict(cacheNames = "billCache#3600", key = "#id")
public ResultJSON deleteBill(Integer id) {
return ResultJSON.ok(this.removeById(id));
}
}
4. 关键注意事项
4.1 配置冲突解决
- 问题 :
RedisTemplate与CacheConfig配置可能冲突 - 建议 :在大多数场景下,使用
CacheConfig统一管理缓存配置
4.2 缓存键生成规则
- 默认格式 :
caching::cacheName::key - 示例 :
caching:billCache::1
4.3 TTL优先级
- 最高 :注解中通过
#指定的TTL(如billCache#3600) - 中等:YAML中针对具体cacheName的配置
- 最低:全局默认TTL配置
4.4 空值缓存策略
yml
spring:
cache:
redis:
cache-null-values: false # 推荐设置为false,避免缓存空值
4.5 最佳实践
- 合理设置TTL:根据数据更新频率设置不同的过期时间
- 避免缓存雪崩:为不同缓存设置不同的TTL
- 及时清理缓存:数据更新后立即清除相关缓存
- 监控缓存命中率:定期检查缓存效果