mirror of https://github.com/elunez/eladmin
194 lines
7.2 KiB
Java
194 lines
7.2 KiB
Java
package me.zhengjie.config;
|
||
|
||
import cn.hutool.core.lang.Assert;
|
||
import com.alibaba.fastjson.JSON;
|
||
import com.alibaba.fastjson.parser.ParserConfig;
|
||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import me.zhengjie.utils.StringUtils;
|
||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||
import org.springframework.cache.Cache;
|
||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||
import org.springframework.cache.annotation.EnableCaching;
|
||
import org.springframework.cache.interceptor.CacheErrorHandler;
|
||
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.connection.RedisConnectionFactory;
|
||
import org.springframework.data.redis.core.RedisOperations;
|
||
import org.springframework.data.redis.core.RedisTemplate;
|
||
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||
import org.springframework.data.redis.serializer.SerializationException;
|
||
import java.nio.charset.Charset;
|
||
import java.nio.charset.StandardCharsets;
|
||
import java.time.Duration;
|
||
|
||
/**
|
||
* @author Zheng Jie
|
||
* @date 2018-11-24
|
||
*/
|
||
@Slf4j
|
||
@Configuration
|
||
@EnableCaching
|
||
@ConditionalOnClass(RedisOperations.class)
|
||
@EnableConfigurationProperties(RedisProperties.class)
|
||
public class RedisConfig extends CachingConfigurerSupport {
|
||
|
||
/**
|
||
* 设置 redis 数据默认过期时间,默认1天
|
||
* 设置@cacheable 序列化方式
|
||
*/
|
||
@Bean
|
||
public RedisCacheConfiguration redisCacheConfiguration(){
|
||
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
|
||
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
|
||
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofDays(1));
|
||
return configuration;
|
||
}
|
||
|
||
@Bean(name = "redisTemplate")
|
||
@ConditionalOnMissingBean(name = "redisTemplate")
|
||
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
||
RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
||
//序列化
|
||
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
|
||
// value值的序列化采用fastJsonRedisSerializer
|
||
template.setValueSerializer(fastJsonRedisSerializer);
|
||
template.setHashValueSerializer(fastJsonRedisSerializer);
|
||
// 全局开启AutoType,这里方便开发,使用全局的方式
|
||
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
|
||
// 建议使用这种方式,小范围指定白名单
|
||
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.domain");
|
||
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.service.dto");
|
||
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.service.dto");
|
||
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.domain");
|
||
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.quartz.domain");
|
||
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.monitor.domain");
|
||
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.security.security");
|
||
// key的序列化采用StringRedisSerializer
|
||
template.setKeySerializer(new StringRedisSerializer());
|
||
template.setHashKeySerializer(new StringRedisSerializer());
|
||
template.setConnectionFactory(redisConnectionFactory);
|
||
return template;
|
||
}
|
||
|
||
/**
|
||
* 自定义缓存key生成策略,默认将使用该策略
|
||
*/
|
||
@Bean
|
||
@Override
|
||
public KeyGenerator keyGenerator() {
|
||
return (target, method, params) -> {
|
||
StringBuilder sb = new StringBuilder();
|
||
sb.append(target.getClass().getName());
|
||
sb.append(method.getName());
|
||
for (Object obj : params) {
|
||
sb.append(JSON.toJSONString(obj).hashCode());
|
||
}
|
||
return sb.toString();
|
||
};
|
||
}
|
||
|
||
@Bean
|
||
@Override
|
||
public CacheErrorHandler errorHandler() {
|
||
// 异常处理,当Redis发生异常时,打印日志,但是程序正常走
|
||
log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
|
||
return new CacheErrorHandler() {
|
||
@Override
|
||
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
|
||
log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
|
||
}
|
||
|
||
@Override
|
||
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
|
||
log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);
|
||
}
|
||
|
||
@Override
|
||
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
|
||
log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);
|
||
}
|
||
|
||
@Override
|
||
public void handleCacheClearError(RuntimeException e, Cache cache) {
|
||
log.error("Redis occur handleCacheClearError:", e);
|
||
}
|
||
};
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* Value 序列化
|
||
*
|
||
* @author /
|
||
* @param <T>
|
||
*/
|
||
class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
|
||
|
||
private Class<T> clazz;
|
||
|
||
FastJsonRedisSerializer(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, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
|
||
}
|
||
|
||
@Override
|
||
public T deserialize(byte[] bytes) throws SerializationException {
|
||
if (bytes == null || bytes.length <= 0) {
|
||
return null;
|
||
}
|
||
String str = new String(bytes, StandardCharsets.UTF_8);
|
||
return JSON.parseObject(str, clazz);
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* 重写序列化器
|
||
*
|
||
* @author /
|
||
*/
|
||
class StringRedisSerializer implements RedisSerializer<Object> {
|
||
|
||
private final Charset charset;
|
||
|
||
StringRedisSerializer() {
|
||
this(StandardCharsets.UTF_8);
|
||
}
|
||
|
||
private StringRedisSerializer(Charset charset) {
|
||
Assert.notNull(charset, "Charset must not be null!");
|
||
this.charset = charset;
|
||
}
|
||
|
||
@Override
|
||
public String deserialize(byte[] bytes) {
|
||
return (bytes == null ? null : new String(bytes, charset));
|
||
}
|
||
|
||
@Override
|
||
public byte[] serialize(Object object) {
|
||
String string = JSON.toJSONString(object);
|
||
if (StringUtils.isBlank(string)) {
|
||
return null;
|
||
}
|
||
string = string.replace("\"", "");
|
||
return string.getBytes(charset);
|
||
}
|
||
}
|