前言:为了将redis缓存部分的代码与业务代码分离开来,我们可以使用@Cacheable注解,该注解可以将方法返回的对象自动存入redis,在访问时又自动先从redis获取。
配置文件
除了基础的redis配置之后,我们还需添加一个config类将CacheManager类注入到容器中,key和value的序列化策略都可以在这里根据需要自由配置。
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCache;
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.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
import java.time.LocalDateTime;
@Configuration
public class RedisTemplateConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 配置序列化(解决乱码的问题)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
// 缓存有效期
// .entryTtl(Duration.ofDays(1))
// 使用StringRedisSerializer来序列化和反序列化redis的key值
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
// 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
//.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(genericJackson2JsonRedisSerializer))
//不添加缓存名称作为前缀
// .disableKeyPrefix()
// 禁用空值
.disableCachingNullValues();
// return RedisCacheManager.builder(connectionFactory)
// .cacheDefaults(config)
// .build();
return new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory), config) {
@Override
public RedisCache getCache(String name) {
RedisCacheConfiguration cacheConfig = config.entryTtl(getDurationUntilNextDay());
return super.createRedisCache(name, cacheConfig);
}
// 设置过期时间到第二天零点
public Duration getDurationUntilNextDay() {
LocalDateTime now = LocalDateTime.now();
LocalDateTime nextDay = now.toLocalDate().plusDays(1).atStartOfDay();
return Duration.between(now, nextDay);
}
};
}
}
业务使用
直接在service层实现类中的方法加上注解即可
@Override
@Cacheable(cacheNames = "company:deploy", key ="#inVo.strYearMonth")
public List<CompanyDeployVo> getDeployDetails(YearMonthInVo inVo) {
......
}
如果对默认的key生成格式不满意,可添加一个KeyGenerator类来自定义生成key的格式,然后在@Cacheable注解上设置keyGenerator属性。
package com.terton.redis.config;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
@Component("customKeyGenerator")
public class CustomKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
// String s = target.toString()+":"+method.getName()+":"+ Arrays.toString(params);
String s = Arrays.toString(params);
return s;
}
}
@Cacheable(cacheNames = "company:deploy", keyGenerator = "customKeyGenerator")
此外,注解还支持指定条件生效,可自行查阅。