yml连接配置:
redis:
cache-one:
host: localhost
port: 6379
database: 0
password: password
config映射,其他参数可自定义:
@Data
@ConfigurationProperties("redis")
public class RedisConfig {
private RedisProperties cacheOne;
/** redis pool最大空闲连接 */
private int maxIdle = 20;
/** redis pool最连接数 */
private int maxTotal = 50;
/** redis pool最小空闲连接 */
private int minIdle = 0;
/** 缓存有效期 */
private Duration entryTtl = Duration.ofHours(24L);
/** 连接超时 */
private Duration connectTimeout = Duration.ofSeconds(15L);
/** 读取超时 */
private Duration readTimeout = Duration.ofSeconds(30L);
}
lettuce连接工厂:
default RedisStandaloneConfiguration connection(RedisConfig redisConfig) {
RedisProperties redisProperties = redisConfig.getCacheOne();
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(redisProperties.getHost());
redisStandaloneConfiguration.setPort(redisProperties.getPort());
redisStandaloneConfiguration.setDatabase(redisProperties.getDatabase());
redisStandaloneConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));
return redisStandaloneConfiguration;
}
default RedisConnectionFactory lettuceConnectionFactory(RedisConfig redisConfig) {
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxIdle(redisConfig.getMaxIdle());
poolConfig.setMaxTotal(redisConfig.getMaxTotal());
poolConfig.setMinIdle(redisConfig.getMinIdle());
LettuceClientConfiguration lettuceClientConfiguration = LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofSeconds(15))
.poolConfig(poolConfig)
.shutdownTimeout(Duration.ZERO)
.build();
LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(connection(redisConfig), lettuceClientConfiguration);
lettuceConnectionFactory.afterPropertiesSet();
return lettuceConnectionFactory;
}
继承CachingConfigurerSupport类,重写keyGenerator和cacheManager方法并注入spring
@Slf4j
@Configuration
@EnableCaching
@EnableConfigurationProperties(RedisConfig.class)
public class RedisCacheConfig extends CachingConfigurerSupport implements LettuceConnection {
@Autowired
private RedisConfig redisConfig;
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(":");
sb.append(method.getName());
if (ArrayUtils.isNotEmpty(params)) {
String collect = Arrays.stream(params).map(x -> x.getClass().getSimpleName()).collect(Collectors.joining(",", "(", ")"));
sb.append(collect);
}
return sb.toString();
};
}
@Bean
@Override
@ConditionalOnProperty({"redis.cache-one.host"})
public RedisCacheManager cacheManager() {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer()))
.entryTtl(redisConfig.getEntryTtl());
RedisCacheManager cacheManager = RedisCacheManager.builder(lettuceConnectionFactory(redisConfig))
.cacheDefaults(redisCacheConfiguration)
.transactionAware()
.build();
cacheManager.afterPropertiesSet();
log.info("RedisCacheManager config success");
return cacheManager;
}
}
序列化配置:
default FastJsonRedisSerializer
redis存储的key和value都有序列化设置
StringRedisSerializer:存进去和取出来都是普通字符串类型
JdkSerializationRedisSerializer:key和value默认序列化方式,存进去是二进制形式,取出来自动还原为原类型,不需要指定还原类型,但需要原类型实现Serializable接口,存取效率最高,数据安全性高,但是数据长度过长占用内存或硬盘空间大
GenericFastJsonRedisSerializer:会生成一个@type属性保存对象类型,默认开启autoTypeSupport,存在安全漏洞问题
GenericJackson2JsonRedisSerializer:会生成一个@Class属性保存对象类型,默认配置了enableDefaultTyping,存在安全漏洞问题
FastJsonRedisSerializer和Jackson2JsonRedisSerializer:虽然可以序列化成json字符串保存,但是反序列化时必需指定类型否则报错:com.alibaba.fastjson.JSONException: autoType is not support,如果序列化对象存在非Object父类还会报类型转换异常
通过自定义FastJsonRedisSerializer支持自动反序列化并提供安全性:
1、FastJsonConfig中配置SerializerFeature.WriteClassName
2、配置全局白名单ParserConfig.getGlobalInstance().addAccept("com.package.entity."),指定反序列化包名,多个包配置多个addAccept
3、如果步骤2配置后仍然报错,则可以开启全局AutoTypeSupport,但会存在一定风险,
ParserConfig.getGlobalInstance().setAutoTypeSupport(true)
注意:白名单配置和AutoTypeSupport都需要全局配置
1、@EnableCaching:注入CacheManger时开启缓存功能,开启@EnableCaching后,yml中spring.cache.type设为none
2、@CacheConfig:注解在类上,统一所有方法的缓存命名空间名称和key
3、@CachePut:更新指定缓存,key存在则覆盖,不存在则插入
4、@CacheEivct:清空指定缓存或所有缓存
5、@Caching:组合注解缓存
以上指定的缓存指的是cacheNames值即默认value值,必须被指定,是一个命名空间,层级之间用冒号:隔开
keyGenerator属性指定被注入spring的KeyGenerator子类Bean
unless用在方法返回之后条件判断,为false时才进行缓存操作
condition用在方法调用之前条件判断,为true时才进行缓存操作
allEntries设为true指定缓存全部过期失效
将通用缓存注解设置在service接口中,自定义cacheNames,也可以在serviceImpl中添加缓存注解,重写方法会覆盖父类的缓存
接口中缓存,继承的是mybatis-plus的基础接口:
@CacheConfig(cacheNames = "SchoolGirl")
public interface SchoolGirlService extends IService {
@Cacheable(key = "#id", unless = "#result==null")
default SchoolGirl findByIdCache(Serializable id) {
return selectById(id);
}
@CachePut(key = "#entity.id", condition = "#entity!=null")
default SchoolGirl saveCache(SchoolGirl entity) {
insertOrUpdate(entity);
return entity;
}
@CacheEvict(key = "#id")
default boolean deleteByIdCache(Serializable id) {
return deleteById(id);
}
@CacheEvict(allEntries = true)
default boolean saveBatchCache(List list) {
return insertOrUpdateBatch(list);
}
}