2022-02-10 16:18:48 +08:00

188 lines
7.9 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.xkrs.common.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
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.*;
import javax.annotation.Resource;
import java.io.IOException;
import java.time.Duration;
/**
* redis配置
* @author tajochen
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{
private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
@Resource
private LettuceConnectionFactory lettuceConnectionFactory;
private static final Duration TIME_TO_LIVE = Duration.ofSeconds(3600*6);
@Bean
@Override
public KeyGenerator keyGenerator() {
// 设置自动key的生成规则配置spring boot的注解进行方法级别的缓存
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(":");
sb.append(method.getName());
for (Object obj : params) {
sb.append(":").append(obj);
}
// logger.info("自动生成Redis Key -> [{}]", rsToUse);
return String.valueOf(sb);
};
}
@Bean
@Override
public CacheManager cacheManager() {
// 关键点spring cache的注解使用的序列化都从这来没有这个配置的话使用的jdk自己的序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
//key序列化方式
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
//value序列化方式
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))
.disableCachingNullValues()
.entryTtl(TIME_TO_LIVE);
RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder
.fromConnectionFactory(lettuceConnectionFactory)
.cacheDefaults(config)
.transactionAware();
return builder.build();
}
/**
* RedisTemplate配置 在单独使用redisTemplate的时候 重新定义序列化方式
*/
@Bean(name = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
// 设置序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
// 配置null值序列化成空字符串
om.getSerializerProvider().setNullValueSerializer(new JsonSerializer<>() {
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString("");
}
});
// 解决jackson无法反序列化LocalDateTime的问题,引入jsr310标准
JavaTimeModule javaTimeModule = new JavaTimeModule();
om.registerModule(javaTimeModule);
om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 其他设置
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置redisTemplate
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
RedisSerializer<?> stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
private RedisSerializer<String> keySerializer() {
return new StringRedisSerializer();
}
private RedisSerializer<Object> valueSerializer() {
// 设置序列化
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(
Object.class);
ObjectMapper om = new ObjectMapper();
// 解决jackson无法反序列化LocalDateTime的问题,引入jsr310标准
JavaTimeModule javaTimeModule = new JavaTimeModule();
om.registerModule(javaTimeModule);
om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 其他设置
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(om);
return jackson2JsonRedisSerializer;
}
@Override
public CacheResolver cacheResolver() {
return null;
}
/**
* 设置数据存入 redis 的序列化方式,并开启事务
*
* @param redisTemplate
* @param factory
*/
private void initRedisTemplate(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) {
//如果不配置Serializer那么存储的时候缺省使用String如果用User类型存储那么会提示错误User can't cast to String
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// 开启事务
redisTemplate.setEnableTransactionSupport(true);
redisTemplate.setConnectionFactory(factory);
}
/**
* 注入封装RedisTemplate 给RedisUtil提供操作类
* @param redisTemplate
* @return RedisUtil
*/
@Bean(name = "redisUtil")
public RedisUtil redisUtil(RedisTemplate<String, Object> redisTemplate) {
RedisUtil redisUtil = new RedisUtil();
redisUtil.setRedisTemplate(redisTemplate);
return redisUtil;
}
@Override
@Bean
public CacheErrorHandler errorHandler() {
// 异常处理当Redis发生异常时打印日志但是程序正常走
logger.info("初始化 -> [{}]", "Redis CacheErrorHandler");
return null;
}
}