前言
spring boot中使用Redis作为缓存系统,如果使用Spring的注解使用缓存,默认是不带失效时间的,需要自己做处理。
一、Spring缓存注解介绍
spring cache 主要使用3个注释标签,即 @Cacheable、@CachePut 和 @CacheEvict。
- @Cacheable
主要针对方法配置,能够根据方法的请求参数对其结果进行缓存。主要参数如下:
属性 | 说明 | 备注 |
---|---|---|
value | 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 | 例如:@Cacheable(value={”cache1”,”cache2”} |
key | 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 | 例如:@Cacheable(value=”cache1”,key=”#id”) |
condition | 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 | 例如:@Cacheable(value=”cache2”,condition=”#userName != null”) |
- @CachePut
主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用。主要参数如下:
属性 | 说明 | 备注 |
---|---|---|
value | 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 | 例如:@CachePut(value={”cache1”,”cache2”} |
key | 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 | 例如:@CachePut(value=”cache1”,key=”#id”) |
condition | 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 | 例如:@CachePut(value=”cache2”,condition=”#userName != null”) |
- @CacheEvict
主要针对方法配置,能够根据一定的条件对缓存进行清空。主要参数如下:
属性 | 说明 | 备注 |
---|---|---|
value | 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 | 例如:@CacheEvict(value={”cache1”,”cache2”} |
key | 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 | 例如:@Cacheable(value=”cache1”,key=”#id”) |
condition | 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 | 例如:@CacheEvict(value=”cache2”,condition=”#userName != null”) |
allEntries | 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存 | 例如:@CachEvict(value=”cache2”,allEntries=true) |
beforeInvocation | 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存 | 例如:@CachEvict(value=”cache2”,beforeInvocation=true) |
另外,如果想清除多个缓存,可以使用@Caching,例如:
@Caching(evict = {
@CacheEvict(value = "auth", key = "'url_map'"),
@CacheEvict(value = "auth", key = "'menus'"),
@CacheEvict(value = "auth", key = "'role_map'")
})
二、自定义缓存的失效时间
1.配置文件内添加配置
spring.cache.type=redis
spring.cache.redis.time-to-live=2000000
spring.cache.cache-names[0]=test
spring.cache.cache-names[1]=auth
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.timeout=1000000
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
spring.redis.lettuce.pool.max-wait=-1
2.redis缓存配置类
package com.iscas.base.biz.config.redis.cache;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iscas.base.biz.config.auth.TokenProps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.io.Serializable;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
* Redis缓存配置
*
* @author zhuquanwen
* @vesion 1.0
* @date 2020/12/7 21:42
* @since jdk1.8
*/
@Configuration
@ConditionalOnProperty(name = "spring.cache.type", havingValue = "redis", matchIfMissing = false)
public class RedisCacheConfig {
@Value("${spring.cache.redis.time-to-live:2000000}")
private int timeToLive;
@Value("${login.random.data.cache.time-to-live}")
private int randomTimeToLive;
@Autowired
private TokenProps tokenProps;
/**
* 序列化配置
*/
@Bean("redisTemplate")
@Primary
public RedisTemplate<String, Serializable> redisTemplate (LettuceConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Serializable> template = new RedisTemplate<>();
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean("cacheManager")
@Primary
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
this.getRedisCacheConfigurationWithTtl(timeToLive), // 默认策略,未配置的 key 会使用这个
this.getRedisCacheConfigurationMap() // 指定 key 策略
);
}
private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
redisCacheConfigurationMap.put("auth", this.getRedisCacheConfigurationWithTtl((int) (tokenProps.getExpire().getSeconds())));
redisCacheConfigurationMap.put("test", this.getRedisCacheConfigurationWithTtl(18000));
redisCacheConfigurationMap.put("loginCache", this.getRedisCacheConfigurationWithTtl(randomTimeToLive));
return redisCacheConfigurationMap;
}
private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
Jackson2JsonRedisSerializer<Object> 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 redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
RedisSerializationContext
.SerializationPair
.fromSerializer(jackson2JsonRedisSerializer)
).entryTtl(Duration.ofSeconds(seconds));
return redisCacheConfiguration;
}
}
其中重点是getRedisCacheConfigurationMap()函数,为每个缓存的value,设置了超时时间。