概要
`Springboot @Cacheable注解中 自定义处理value/cacheNames实现自定义过期时间
例如:
@Cacheable(value = “user#200#s”) 实现rediskey为user的过期时间为200s
技术细节
在项目中引入这些配置:
1.自定义@Cacheable中value字段的解析处理
public class MyRedisCacheManager extends RedisCacheManager {
private final static List<String> optionalUnits = ListUtil.of("ms", "s", "m", "h", "d");
private final static String defaultTimeUnit = "s";
public MyRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
super(cacheWriter, defaultCacheConfiguration);
}
/**
* 使用@Cacheable时,value中通过#号隔开,第一位是name,第二位是有效时间,第三位是单位,默认可以不传(默认为秒s)
* 第二位仅限填写:ms,s,m,h,d其中,ms:毫秒,s:秒,m:分钟,h:小时,d:天
*
* @param name
* @param cacheConfig
* @return
*/
@Override
protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
String[] array = StringUtils.split(name, "#");
name = array[0];
// 解析 @Cacheable 注解的 value 属性用以单独设置有效期
if (array.length > 1) {
long ttl = Long.parseLong(array[1]);
cacheConfig = setValidityPeriod(array, cacheConfig);
}
return super.createRedisCache(name, cacheConfig);
}
/**
* 设置有效期
* 根据时间单位将需要设置的有效期转换为对应的Duration对象
*
* @param array 时间单位数组
* @param cacheConfig 缓存配置
* @return 设置有效期后的缓存配置
*/
private RedisCacheConfiguration setValidityPeriod(String[] array, RedisCacheConfiguration cacheConfig) {
String unit = defaultTimeUnit; // 设置默认时间单位
if (array.length > 2) { // 如果数组长度大于2
String tempUnit = array[2]; // 创建临时变量tempUnit,并赋值为数组第3个元素
if (!optionalUnits.contains(tempUnit)) { // 如果临时变量tempUnit不在optionalUnits中
throw new RuntimeException("Incorrect time unit setting"); // 抛出运行时异常,提示时间单位设置不正确
}
unit = tempUnit; // 将unit的值设置为tempUnit
}
switch (unit) {
case "ms":
// 单位为毫秒
cacheConfig = cacheConfig.entryTtl(Duration.ofMillis(Long.parseLong(array[1])));
break;
case "s":
// 单位为秒
cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(Long.parseLong(array[1])));
break;
case "m":
// 单位为分钟
cacheConfig = cacheConfig.entryTtl(Duration.ofMinutes(Long.parseLong(array[1])));
break;
case "h":
// 单位为小时
cacheConfig = cacheConfig.entryTtl(Duration.ofHours(Long.parseLong(array[1])));
break;
case "d":
// 单位为天
cacheConfig = cacheConfig.entryTtl(Duration.ofDays(Long.parseLong(array[1])));
break;
default:
break;
}
return cacheConfig;
}
}
2.Redis使用FastJson序列化
/**
* Redis使用FastJson序列化
*
* @author logistics
*/
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
{
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
public FastJson2JsonRedisSerializer(Class<T> clazz)
{
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException
{
if (t == null)
{
return new byte[0];
}
return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException
{
if (bytes == null || bytes.length <= 0)
{
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType);
}
}
3.redis配置
/**
* redis配置
*
* @author
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
private RedisSerializer<String> keySerializer() {
// 用于序列化 Redis 的 key 的序列化规则
return new StringRedisSerializer();
}
private RedisSerializer<Object> valueSerializer() {
// 用于序列化 Redis 的 value 的序列化规则
return new FastJson2JsonRedisSerializer(Object.class);
}
public static final String CACHE_PREFIX = "crowd:";
/**
* CacheManager 配置
*
* @param redisConnectionFactory Redis 连接工厂
* @return CacheManager 实例
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return new MyRedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory), defaultCacheConfig());
}
/**
* 设置 Redis 的 key 的序列化规则。
* 设置 Redis 的 value 的序列化规则。
* 计算 Redis 的 key 前缀。
* 全局设置 @Cacheable 注解缓存的有效期。
*
* @return RedisCacheConfiguration 实例
*/
private RedisCacheConfiguration defaultCacheConfig() {
return RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))
// .computePrefixWith(name -> CACHE_PREFIX + name + ":")
// .entryTtl(Duration.ofSeconds(600))
;
}
}
常用属性说明
● cacheNames/value :用来指定缓存组件的名字
● key :缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 spEL 表达式来编写)
● keyGenerator :key 的生成器。 key 和 keyGenerator 二选一使用
● cacheManager :可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。
● condition :可以用来指定符合条件的情况下才缓存
● unless :否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过 #result 获取方法结果)
● sync :是否使用异步模式。