目录
实现步骤
1. 在 pom.xml 配置文件中添加如下依赖
2. 在 application.properties 中添加如下配置
3. 新建 RedisConfig.class,继承 CachingConfigurerSupport,添加如下方法
4. 新建 RedisService.class 添加如下方法
注意:cacheKeyGenerator 是注入的 bean,实现类如下
5. 测试一下
注意
上一章已经介绍了如何在 SpringBoot 中如何使用缓存,本章将介绍如何将缓存和 Redis 结合使用
实现步骤
1. 在 pom.xml 配置文件中添加如下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. 在 application.properties 中添加如下配置
############################## redis 配置 ##############################
spring.redis.url = redis://localhost:6379
# 连接池最大活动连接数
spring.redis.lettuce.pool.max-active = 10
# 连接池中最小空闲连接数
spring.redis.lettuce.pool.min-idle = 5
# 最大连接等待时间
spring.redis.lettuce.pool.max-wait = 10ms
3. 新建 RedisConfig.class,继承 CachingConfigurerSupport,添加如下方法
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
/**
* RedisTemplate 序列化配置
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
StringRedisSerializer keySerializer = new StringRedisSerializer();
template.setKeySerializer(keySerializer);
template.setHashKeySerializer(keySerializer);
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
/**
* 注册缓存管理器
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
// 设置缓存 20 秒过期时间
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(20))
.disableCachingNullValues();
return RedisCacheManager.builder(factory).cacheDefaults(config).transactionAware().build();
}
}
4. 新建 RedisService.class 添加如下方法
@Service
@CacheConfig(cacheNames={"test"}, keyGenerator="cacheKeyGenerator")
public class RedisService {
// 该注解将向缓存中添加字符串
@Cacheable
public String save1() {
System.out.println(new Date() + " --> 没有从缓存取值");
return "ramos";
}
// 该注解将向缓存中添加 user 对象
@Cacheable
public User save2() {
System.out.println(new Date() + " --> 没有从缓存取值");
return new User(1, "dufu");
}
// 该注解将会向缓存中 添加/更新 新的值
// 与 @Cacheable 不同的是, 如下方法中的代码都会执行
@CachePut
public String put(String value) {
System.out.println(new Date() + " 添加了 value --> " + value);
return value;
}
// 该注解将会把缓存中的值删除掉
// 与 @Cacheable 不同的是, 如下方法中的代码都会执行
@CacheEvict
public void delete() {
System.out.println(new Date() + " 删除了 value");
}
}
注意:cacheKeyGenerator 是注入的 bean,实现类如下
@Component
// 自定义缓存生成 key 的方式
public class CacheKeyGenerator implements KeyGenerator {
// 将目标类的类名作为 key 值
@Override
public Object generate(Object target, Method method, Object... params) {
return target.getClass().getName() + method.getName();
}
}
这里明确了 key 的生成是 由类名 + 方法名 组成,因为如果设置 key 的值为固定值的话,有可能会出现转换错误,例如:假如 save1() 和 save2() 两个方法的返回值不一致,但是缓存的 key 值一样的话,可能会第一次调用 save1() 放入 { test: ramos } , 第二次调用 save2() 就会取出 Ramos(String),但是 save2() 的返回值类型是 User,这样就会出错
5. 测试一下
注意
1. 自定义的实体类要被缓存,就必须实现 IO 的 Serializable 接口
@Data
public class User implements Serializable {
private static final long serialVersionUI = 1L;
private int id;
private String name;
}
2. 集成缓存会与 SpringBoot 的热部署冲突,报错:class XX cannot be cast to class XX ,XX is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader
暂未找到两全其美的解决办法;只能注释掉热部署依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>