SpringCache基本配置类
起步依赖
java
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
SpringCacheConfig
同时配置带过期时间的CacheManager
自定义Json
序列化方式存储
java
import cn.hutool.core.util.RandomUtil;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.support.NoOpCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* spring cache配置
*/
@Configuration
public class SpringCacheConfig {
@Value("${cache.enabled}")
private Boolean cacheEnabled;
/**
* 随机数上界-1天时间内随机数
*/
private static final long CACHE_RANDOM_LIMIT = 24 * 60 * 60 * 1000L;
/**
* 获取缓存时间
* 缓存时间=sourceCacheTtl+random limit
*
* @param sourceCacheTtl sourceCacheTtl
* @param limit limit
* @return long
*/
private long cacheTtlWithRandom(long sourceCacheTtl, long limit) {
long random = RandomUtil.randomLong(limit);
return sourceCacheTtl + random;
}
/**
* 同时随机过期时间解决缓存雪崩问题
*
* @return CacheManager
*/
@Bean("testCache")
public CacheManager cacheManager1Day(RedisConnectionFactory connectionFactory) {
if (!cacheEnabled) {
// 禁用缓存,不会存储
return new NoOpCacheManager();
}
// 3天过期时间,转换成毫秒
long threeDaysInMillis = 3 * 24 * 60 * 60 * 1000L;
// 过期时间和最大空闲时间都设为3天+随机时间
long trueTtl = cacheTtlWithRandom(threeDaysInMillis, CACHE_RANDOM_LIMIT);
RedisCacheConfiguration config = instanceConfig(trueTtl);
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.transactionAware()
.build();
}
/**
* 初始化config
*
* @param ttl 超时时间
* @return RedisCacheConfiguration
*/
private RedisCacheConfiguration instanceConfig(Long ttl) {
// value存储为JSON格式
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
// 指定objectMapper带输入类型的序列化,如果不指定redis中则存储纯json,序列化返回后解析默认为LinkedHashMap
// 需要自己转换类型,指定序列化类型后无需再进行转化
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
// 处理LocalDateTime
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.registerModule(new JavaTimeModule());
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(ttl))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
}
}
带过期时间的CacheManager
使用方法如下
java
@Cacheable(cacheNames = "TestName",
key = "'123456'",
cacheManager = "testCache",
sync = true)
其中存储到Redis
中的key
的规则为
- 当没有配置
key
时:key=cacheNames+::+SimpleKey []
,如TestName::SimpleKey []
- 当配置了
key
时:key=cacheNames+::+key
,如TestName::123456