本文基于Springboot2.0.4 数据库使用mysql
由于在redis的客户端上采用了Letture
这里讲一下jedis和Letture的简单说明
所以一开始在启动程序的时候就遇到这个错误
Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.GenericObjectPoolConfig
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_91]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_91]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_91]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_91]
... 49 common frames omitted
在pom文件中引入下面的包
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-pool2artifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
spring:
application:
name: redis-demo
cache:
type: redis
redis:
time-to-live: 20000 #缓存超时时间ms
cache-null-values: false #是否缓存空值
redis:
port: 6379
host: localhost
lettuce:
pool:
max-active: 8
max-wait: -1
max-idle: 8
min-idle: 0
timeout: 10000 #redis 连接超时时间ms
database: 0
RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
defaultCacheConfig.entryTtl(Duration
.ofSeconds(30L));
defaultCacheConfig.disableCachingNullValues();
这种配置是错误的 看完entryTtl和disableCachingNullValues的返回值均为RedisCacheConfiguration 所以上面的配置方法是无效的
下面是配置源码
@Bean
CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
/* 默认配置, 默认超时时间为30s */
RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration
.ofSeconds(30L)).disableCachingNullValues();
/* 配置test的超时时间为120s*/
RedisCacheManager cacheManager = RedisCacheManager.builder(RedisCacheWriter.lockingRedisCacheWriter
(connectionFactory)).cacheDefaults(defaultCacheConfig).withInitialCacheConfigurations(singletonMap
("test", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(120L))
.disableCachingNullValues())).transactionAware().build();
return cacheManager;
}
@Cacheable(value = "test", key = "#root.targetClass + '_' + #p0 + '_' + #p1")
到此使用简单的注解式的redis缓存配置就结束了
实际在项目中会遇到某些特殊的场景 某些缓存更希望用一个线程负责更新缓存 而不是单独的请求去判断 本文缓存更新采用了RedisTemplate手动写入的方式
5. RedisTemplate的配置
一开始使用的序列化方式不对 导致序列化出来的和上面系统自动缓存的不一致,导致上面读取缓存的时候总是值错误 在网上看了很多资料 后来看了源码 试了很多序列化方式 发现默认的是这个序列化类JdkSerializationRedisSerializer
在同时使用了上面注解的缓存和这种手动缓存的时候 特别需要注意的就是这个序列化方式的一致性 也可以改上面默认的序列化方式
@Bean
public RedisTemplate<String, Integer> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Integer> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.setExposeConnection(true);
redisTemplate.setConnectionFactory(factory);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Component
public class MyRedisCacheManager {
@Autowired
private RedisTemplate redisTemplate;
/* 插入数据或者更新数据 */
public void insert(String key, Object value, long timeout, TimeUnit timeUnit) {
if (StringUtils.isBlank(key) || !ObjectUtils.anyNotNull(value)) {
return;
}
if (timeout == 0) {
redisTemplate.opsForValue().set(key, value);
} else {
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
}
public void delete(String key) {
redisTemplate.opsForValue().getOperations().delete(key);
}
}
这里是整个项目的源码 可供参考GITHUB