提交 2c54e373 编写于 作者: zhouweidong's avatar zhouweidong

缓存整改

上级 79c11190
...@@ -4,8 +4,6 @@ TARGET=PSSYSTEM ...@@ -4,8 +4,6 @@ TARGET=PSSYSTEM
package ${pub.getPKGCodeName()}.util.cache; package ${pub.getPKGCodeName()}.util.cache;
import com.github.benmanes.caffeine.cache.CaffeineSpec; import com.github.benmanes.caffeine.cache.CaffeineSpec;
import ${pub.getPKGCodeName()}.util.cache.cacheManager.CaffeineCacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.cache.CacheProperties; import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
...@@ -15,6 +13,7 @@ import org.springframework.context.annotation.Bean; ...@@ -15,6 +13,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import ${pub.getPKGCodeName()}.util.cache.cacheManager.CaffeineCacheManager;
/** /**
* Caffeine缓存配置类 * Caffeine缓存配置类
...@@ -25,19 +24,19 @@ import org.springframework.util.StringUtils; ...@@ -25,19 +24,19 @@ import org.springframework.util.StringUtils;
@ConditionalOnExpression("'${r'${ibiz.cacheLevel:None}'}'.equals('L1')") @ConditionalOnExpression("'${r'${ibiz.cacheLevel:None}'}'.equals('L1')")
public class CaffeineCacheConfig { public class CaffeineCacheConfig {
@Autowired /**
private CacheProperties cacheProperties; * Caffeine配置:设置过期时间
* @return
@Autowired */
private CaffeineCacheManager caffeineCacheManager;
@Bean @Bean
@Primary @Primary
public CacheManager cacheManager() { public CacheManager cacheManager(CacheProperties cacheProperties) {
String specification = cacheProperties.getCaffeine().getSpec(); CaffeineCacheManager caffeineCacheManager=new CaffeineCacheManager();
if (StringUtils.hasText(specification)) { String strCacheConfig = cacheProperties.getCaffeine().getSpec();
caffeineCacheManager.setCaffeineSpec(CaffeineSpec.parse(specification)); if (StringUtils.hasText(strCacheConfig)) {
caffeineCacheManager.setCaffeineCacheConfig(CaffeineSpec.parse(strCacheConfig));
} }
return caffeineCacheManager; return caffeineCacheManager;
} }
} }
\ No newline at end of file
...@@ -3,16 +3,11 @@ TARGET=PSSYSTEM ...@@ -3,16 +3,11 @@ TARGET=PSSYSTEM
</#ibiztemplate> </#ibiztemplate>
package ${pub.getPKGCodeName()}.util.cache; package ${pub.getPKGCodeName()}.util.cache;
import com.alibaba.fastjson.parser.ParserConfig;
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.benmanes.caffeine.cache.CaffeineSpec; import com.github.benmanes.caffeine.cache.CaffeineSpec;
import ${pub.getPKGCodeName()}.util.cache.cacheManager.LayeringCacheManager; import org.springframework.beans.factory.annotation.Value;
import ${pub.getPKGCodeName()}.util.cache.redis.KryoRedisSerializer;
import ${pub.getPKGCodeName()}.util.cache.redis.StringRedisSerializer;
import ${pub.getPKGCodeName()}.util.enums.RedisChannelTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.cache.CacheProperties; import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
...@@ -22,14 +17,19 @@ import org.springframework.context.annotation.Bean; ...@@ -22,14 +17,19 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration; 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.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.time.Duration;
import ${pub.getPKGCodeName()}.util.cache.cacheManager.LayeringCacheManager;
import ${pub.getPKGCodeName()}.util.cache.listener.RedisMessageListener;
import ${pub.getPKGCodeName()}.util.cache.redis.CustomJacksonSerializer;
import ${pub.getPKGCodeName()}.util.enums.RedisChannelTopic;
/** /**
* 缓存配置类 * 缓存配置类
...@@ -42,83 +42,91 @@ import org.springframework.util.StringUtils; ...@@ -42,83 +42,91 @@ import org.springframework.util.StringUtils;
@ConditionalOnExpression("'${r'${ibiz.cacheLevel:None}'}'.equals('L2')") @ConditionalOnExpression("'${r'${ibiz.cacheLevel:None}'}'.equals('L2')")
public class RedisCacheConfig { public class RedisCacheConfig {
@Autowired @Value("${r'${spring.cache.redis.time-to-live:3600}'}")
private RedisCacheWriter redisCacheWriter; private long timeToLive;
@Autowired
private RedisCacheConfiguration configuration;
@Autowired
LayeringCacheManager layeringCacheManager;
@Autowired
private CacheProperties cacheProperties;
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory connectionFactory) {
return RedisCacheManager.create(connectionFactory);
}
/**
* 分层缓存管理器
* @param redisConnectionFactory
* @param cacheProperties
* @return
*/
@Bean @Bean
public RedisCacheWriter redisCacheWriter(RedisConnectionFactory connectionFactory){ @Primary
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory ,CacheProperties cacheProperties){
return redisCacheWriter; LayeringCacheManager layeringCacheManager=new LayeringCacheManager(redisCacheWriter(redisConnectionFactory),redisCacheConfiguration(),redisTemplate(redisConnectionFactory));
String strCacheConfig = cacheProperties.getCaffeine().getSpec();
if (StringUtils.hasText(strCacheConfig)) {
layeringCacheManager.setCaffeineCacheConfig(CaffeineSpec.parse(strCacheConfig));
}
return layeringCacheManager;
} }
/** /**
* 重写Redis序列化方式,使用Json方式: * redis配置:设置过期时间及序列化方式
* 当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializerStringRedisTemplate默认使用的是StringRedisSerializer
* Spring Data JPA为我们提供了下面的Serializer
* GenericToStringSerializerJackson2JsonRedisSerializerJacksonJsonRedisSerializerJdkSerializationRedisSerializerOxmSerializerStringRedisSerializer
* 在此我们将自己配置RedisTemplate并定义Serializer
*
* @param redisConnectionFactory
* @return * @return
*/ */
@Bean @Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { public RedisCacheConfiguration redisCacheConfiguration(){
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); CustomJacksonSerializer jackson2JsonRedisSerializer = new CustomJacksonSerializer(Object.class);
redisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
ObjectMapper om = new ObjectMapper(); ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om); jackson2JsonRedisSerializer.setObjectMapper(om);
ParserConfig.getGlobalInstance().setAutoTypeSupport(true); RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
KryoRedisSerializer<Object> kryoRedisSerializer = new KryoRedisSerializer<>(Object.class); .entryTtl(Duration.ofSeconds(timeToLive))
redisTemplate.setValueSerializer(kryoRedisSerializer);// 设置值(value)的序列化采用KryoRedisSerializer .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
redisTemplate.setHashValueSerializer(kryoRedisSerializer); .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
redisTemplate.setKeySerializer(new StringRedisSerializer());// 设置键(key)的序列化采用StringRedisSerializer .disableCachingNullValues();
redisTemplate.setHashKeySerializer(new StringRedisSerializer()); return configuration;
redisTemplate.afterPropertiesSet();
return redisTemplate;
} }
/**
* 创建redis缓存
* @param connectionFactory
* @return
*/
@Bean @Bean
@Primary public RedisCacheWriter redisCacheWriter(RedisConnectionFactory connectionFactory){
public CacheManager cacheManager() { RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
setCaffeineCacheConfig(layeringCacheManager);//Caffeine缓存设置 return redisCacheWriter;
layeringCacheManager.setRedisCacheWriter(redisCacheWriter);
layeringCacheManager.setRedisConfiguration(configuration);
return layeringCacheManager;
} }
private void setCaffeineCacheConfig(LayeringCacheManager layeringCacheManager) { /**
String specification = cacheProperties.getCaffeine().getSpec(); * 发送redis广播
if (StringUtils.hasText(specification)) { * @param factory
layeringCacheManager.setCaffeineSpec(CaffeineSpec.parse(specification)); * @return
} */
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
CustomJacksonSerializer jacksonSerial = new CustomJacksonSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
jacksonSerial.setObjectMapper(om);
template.setValueSerializer(jacksonSerial);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jacksonSerial);
template.afterPropertiesSet();
return template;
} }
/** /**
* 监听redis指定频道 * 监听redis指定频道
* @param redisConnectionFactory * @param redisConnectionFactory
* @param messageListener * @param cacheManager
* @param redisTemplate
* @return * @return
*/ */
@Bean @Bean
RedisMessageListenerContainer redisContainer(RedisConnectionFactory redisConnectionFactory, MessageListenerAdapter messageListener) { RedisMessageListenerContainer redisContainer(RedisConnectionFactory redisConnectionFactory, CacheManager cacheManager , RedisTemplate redisTemplate) {
final RedisMessageListenerContainer container = new RedisMessageListenerContainer(); RedisMessageListenerContainer container = new RedisMessageListenerContainer();
MessageListenerAdapter messageListener=new RedisMessageListener(cacheManager,redisTemplate);
container.setConnectionFactory(redisConnectionFactory); container.setConnectionFactory(redisConnectionFactory);
container.addMessageListener(messageListener, RedisChannelTopic.REDIS_CACHE_DELETE_TOPIC.getChannelTopic()); container.addMessageListener(messageListener, RedisChannelTopic.REDIS_CACHE_DELETE_TOPIC.getChannelTopic());
container.addMessageListener(messageListener, RedisChannelTopic.REDIS_CACHE_CLEAR_TOPIC.getChannelTopic()); container.addMessageListener(messageListener, RedisChannelTopic.REDIS_CACHE_CLEAR_TOPIC.getChannelTopic());
return container; return container;
} }
} }
\ No newline at end of file
...@@ -15,5 +15,4 @@ public class CusRedisCache extends RedisCache { ...@@ -15,5 +15,4 @@ public class CusRedisCache extends RedisCache {
public CusRedisCache(String name, RedisCacheWriter redisCacheWriter, RedisCacheConfiguration configuration) { public CusRedisCache(String name, RedisCacheWriter redisCacheWriter, RedisCacheConfiguration configuration) {
super(name, redisCacheWriter, configuration); super(name, redisCacheWriter, configuration);
} }
} }
...@@ -3,58 +3,55 @@ TARGET=PSSYSTEM ...@@ -3,58 +3,55 @@ TARGET=PSSYSTEM
</#ibiztemplate> </#ibiztemplate>
package ${pub.getPKGCodeName()}.util.cache.cache; package ${pub.getPKGCodeName()}.util.cache.cache;
import ${pub.getPKGCodeName()}.util.cache.listener.RedisPublisher; import lombok.Data;
import ${pub.getPKGCodeName()}.util.enums.RedisChannelTopic; import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.caffeine.CaffeineCache; import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.AbstractValueAdaptingCache; import org.springframework.cache.support.AbstractValueAdaptingCache;
import org.springframework.cache.support.NullValue; import org.springframework.cache.support.NullValue;
import org.springframework.data.redis.cache.RedisCache; import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisOperations;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import ${pub.getPKGCodeName()}.util.cache.listener.RedisPublisher;
import ${pub.getPKGCodeName()}.util.enums.RedisChannelTopic;
/** /**
* 缓存分层类 * 缓存分层类
* 1级缓存为caffeine * 1级缓存为caffeine
* 2级缓存为redis * 2级缓存为redis
*/ */
@Slf4j
public class LayeringCache extends AbstractValueAdaptingCache { public class LayeringCache extends AbstractValueAdaptingCache {
Logger logger = LoggerFactory.getLogger(LayeringCache.class);
/** /**
* 缓存的名称 * 缓存的名称
*/ */
private final String name; private String cacheName;
/** /**
* redis缓存 * Caffeine缓存
*/ */
private RedisCache redisCache; private CaffeineCache caffeineCache;
/** /**
* Caffeine缓存 * redis缓存
*/ */
private final CaffeineCache caffeineCache; private RedisCache redisCache;
/** /**
* redis消息发布 * redis消息发布
*/ */
RedisOperations<? extends Object, ? extends Object> redisOperations; RedisOperations<? extends Object, ? extends Object> redisOperations;
public LayeringCache(String name ,RedisOperations redisOperations, com.github.benmanes.caffeine.cache.Cache<Object, Object> caffeineCache, public LayeringCache(String cacheName , CaffeineCache caffeineCache, RedisCache redisCache, RedisOperations redisOperations) {
RedisCacheWriter redisCacheWriter, RedisCacheConfiguration configuration) {
super(true); super(true);
this.name = name; this.cacheName = cacheName;
this.redisCache = new CusRedisCache(name, redisCacheWriter, configuration); this.caffeineCache = caffeineCache;
this.caffeineCache = new CaffeineCache(name, caffeineCache, true); this.redisCache = redisCache;
this.redisOperations=redisOperations; this.redisOperations=redisOperations;
} }
@Override @Override
public String getName() { public String getName() {
return this.name; return this.cacheName;
} }
@Override @Override
...@@ -64,40 +61,34 @@ public class LayeringCache extends AbstractValueAdaptingCache { ...@@ -64,40 +61,34 @@ public class LayeringCache extends AbstractValueAdaptingCache {
@Override @Override
public ValueWrapper get(Object key) { public ValueWrapper get(Object key) {
// 查询一级缓存
ValueWrapper wrapper = caffeineCache.get(key); ValueWrapper wrapper = caffeineCache.get(key);
logger.debug("查询一级缓存 key:{},value:{}", key,wrapper); log.debug("查询一级缓存 key:{},value:{}", key,wrapper);
if (wrapper == null) { if (wrapper == null) {
// 查询二级缓存
wrapper = redisCache.get(key); wrapper = redisCache.get(key);
caffeineCache.put(key, wrapper == null ? null : wrapper.get()); caffeineCache.put(key, wrapper == null ? null : wrapper.get());
logger.debug("查询二级缓存,并将数据放到一级缓存。 key:{}", key); log.debug("查询二级缓存,并将数据放到一级缓存。 key:{}", key);
} }
return wrapper; return wrapper;
} }
@Override @Override
public <T> T get(Object key, Class<T> type) { public <T> T get(Object key, Class<T> type) {
// 查询一级缓存
T value = caffeineCache.get(key, type); T value = caffeineCache.get(key, type);
logger.debug("查询一级缓存 key:{}", key); log.debug("查询一级缓存 key:{}", key);
if (value == null) { if (value == null) {
// 查询二级缓存
value = redisCache.get(key, type); value = redisCache.get(key, type);
caffeineCache.put(key, value); caffeineCache.put(key, value);
logger.debug("查询二级缓存,并将数据放到一级缓存。 key:{}", key); log.debug("查询二级缓存,并将数据放到一级缓存。 key:{}", key);
} }
return value; return value;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public <T> T get(Object key, Callable<T> valueLoader) { public <T> T get(Object key, Callable<T> valueLoader) {
// 查询一级缓存,如果一级缓存没有值则调用getForSecondaryCache(k, valueLoader)查询二级缓存 T value = (T) caffeineCache.getNativeCache().get(key, k -> getSecondCacheValue(k, valueLoader));
T value = (T) caffeineCache.getNativeCache().get(key, k -> getSecondCache(k, valueLoader));
if(value==null) { if(value==null) {
// 直接查询二级缓存 value = (T) getSecondCacheValue(key, valueLoader);
value = (T) getSecondCache(key, valueLoader);
} }
if (value instanceof NullValue) { if (value instanceof NullValue) {
return null; return null;
...@@ -122,11 +113,11 @@ public class LayeringCache extends AbstractValueAdaptingCache { ...@@ -122,11 +113,11 @@ public class LayeringCache extends AbstractValueAdaptingCache {
redisCache.evict(key); //清除redis中的二级缓存 redisCache.evict(key); //清除redis中的二级缓存
caffeineCache.evict(key);//清除本机一级缓存 caffeineCache.evict(key);//清除本机一级缓存
Map<String, Object> message = new HashMap<>(); Map<String, Object> message = new HashMap<>();
message.put("cacheName", name); message.put("cacheName", cacheName);
message.put("key", key); message.put("key", key);
RedisPublisher redisPublisher = new RedisPublisher(redisOperations, RedisChannelTopic.REDIS_CACHE_DELETE_TOPIC.getChannelTopic());// 创建redis发布者 RedisPublisher redisPublisher = new RedisPublisher(redisOperations, RedisChannelTopic.REDIS_CACHE_DELETE_TOPIC.getChannelTopic());// 创建redis发布者
redisPublisher.publisher(message);//发布消息,清除其它集群机器中的一级缓存 redisPublisher.publisher(message);//发布消息,清除其它集群机器中的一级缓存
logger.debug(String.format("清除二级缓存数据[%s]", key)); log.debug(String.format("清除二级缓存数据[%s]", key));
} }
@Override @Override
...@@ -134,7 +125,7 @@ public class LayeringCache extends AbstractValueAdaptingCache { ...@@ -134,7 +125,7 @@ public class LayeringCache extends AbstractValueAdaptingCache {
redisCache.clear(); //清除redis中的二级缓存 redisCache.clear(); //清除redis中的二级缓存
caffeineCache.clear();//清除本机一级缓存 caffeineCache.clear();//清除本机一级缓存
Map<String, Object> message = new HashMap<>(); Map<String, Object> message = new HashMap<>();
message.put("cacheName", name); message.put("cacheName", cacheName);
RedisPublisher redisPublisher = new RedisPublisher(redisOperations, RedisChannelTopic.REDIS_CACHE_CLEAR_TOPIC.getChannelTopic());// 创建redis发布者 RedisPublisher redisPublisher = new RedisPublisher(redisOperations, RedisChannelTopic.REDIS_CACHE_CLEAR_TOPIC.getChannelTopic());// 创建redis发布者
redisPublisher.publisher(message);//发布消息,清除其它集群机器中的一级缓存 redisPublisher.publisher(message);//发布消息,清除其它集群机器中的一级缓存
} }
...@@ -142,31 +133,39 @@ public class LayeringCache extends AbstractValueAdaptingCache { ...@@ -142,31 +133,39 @@ public class LayeringCache extends AbstractValueAdaptingCache {
@Override @Override
protected Object lookup(Object key) { protected Object lookup(Object key) {
Object value = caffeineCache.get(key); Object value = caffeineCache.get(key);
logger.debug("查询一级缓存 key:{}", key); log.debug("查询一级缓存 key:{}", key);
if (value == null) { if (value == null) {
value = redisCache.get(key); value = redisCache.get(key);
logger.debug("查询二级缓存 key:{}", key); log.debug("查询二级缓存 key:{}", key);
} }
return value; return value;
} }
/** /**
* 查询二级缓存 * 获取caffeine缓存
* @param key
* @param valueLoader
* @return * @return
*/ */
private <T> Object getSecondCache(Object key, Callable<T> valueLoader) { public CaffeineCache getFirstCache() {
T value = redisCache.get(key, valueLoader); return this.caffeineCache;
logger.debug("查询二级缓存 key:{}", key);
return toStoreValue(value);
} }
/** /**
* 获取caffeine缓存 * 获取redis缓存
* @return * @return
*/ */
public CaffeineCache getFirstCache() { public RedisCache getSecondCache() {
return this.caffeineCache; return this.redisCache;
}
/**
* 查询二级缓存
* @param key
* @param valueLoader
* @return
*/
private <T> Object getSecondCacheValue(Object key, Callable<T> valueLoader) {
T value = redisCache.get(key, valueLoader);
log.debug("查询二级缓存 key:{}", key);
return toStoreValue(value);
} }
} }
...@@ -3,19 +3,15 @@ TARGET=PSSYSTEM ...@@ -3,19 +3,15 @@ TARGET=PSSYSTEM
</#ibiztemplate> </#ibiztemplate>
package ${pub.getPKGCodeName()}.util.cache.cacheManager; package ${pub.getPKGCodeName()}.util.cache.cacheManager;
import lombok.Data;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.CaffeineSpec; import com.github.benmanes.caffeine.cache.CaffeineSpec;
import lombok.Data;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache; import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -24,37 +20,31 @@ import java.util.concurrent.TimeUnit; ...@@ -24,37 +20,31 @@ import java.util.concurrent.TimeUnit;
* Caffeine本地缓存 * Caffeine本地缓存
*/ */
@Data @Data
@Component
@ConditionalOnExpression("'${r'${ibiz.cacheLevel:None}'}'.equals('L1')")
public class CaffeineCacheManager implements CacheManager { public class CaffeineCacheManager implements CacheManager {
private static final int DEFAULT_EXPIRE_AFTER_WRITE = 1;
private static final int DEFAULT_INITIAL_CAPACITY = 5;
private static final int DEFAULT_MAXIMUM_SIZE = 1_000;
private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<String, Cache>(16); private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<String, Cache>(16);
private static final int default_expire_after_write = 1;
/** private static final int default_initial_capacity = 5;
* 缓存默认设置 private static final int default_maximum_size = 1_000;
*/
private Caffeine<Object, Object> cacheBuilder = Caffeine.newBuilder() private Caffeine<Object, Object> cacheBuilder = Caffeine.newBuilder()
.expireAfterAccess(DEFAULT_EXPIRE_AFTER_WRITE, TimeUnit.HOURS) .expireAfterAccess(default_expire_after_write, TimeUnit.HOURS)
.initialCapacity(DEFAULT_INITIAL_CAPACITY) .initialCapacity(default_initial_capacity)
.maximumSize(DEFAULT_MAXIMUM_SIZE); .maximumSize(default_maximum_size);
/** /**
* 获取缓存对象 * 获取缓存对象
* @param name * @param cacheName
* @return * @return
*/ */
@Override @Override
public Cache getCache(String name) { public Cache getCache(String cacheName) {
Cache cache = this.cacheMap.get(name); Cache cache = this.cacheMap.get(cacheName);
if (cache == null) { if (cache == null) {
synchronized (this.cacheMap) { synchronized (this.cacheMap) {
cache = this.cacheMap.get(name); cache = this.cacheMap.get(cacheName);
if (cache == null) { if (cache == null) {
cache = createCache(name); cache = createCache(cacheName);
this.cacheMap.put(name, cache); this.cacheMap.put(cacheName, cache);
} }
} }
} }
...@@ -62,41 +52,32 @@ public class CaffeineCacheManager implements CacheManager { ...@@ -62,41 +52,32 @@ public class CaffeineCacheManager implements CacheManager {
} }
/** /**
* 获取缓存名 * 创建缓存
* @param cacheName
* @return * @return
*/ */
@Override protected Cache createCache(String cacheName) {
public Collection<String> getCacheNames() { return new CaffeineCache(cacheName, this.cacheBuilder.build(), true);
return Collections.unmodifiableSet(this.cacheMap.keySet());
} }
/** /**
* 创建缓存 * 获取缓存名
* @param name
* @return * @return
*/ */
protected Cache createCache(String name) { @Override
return new CaffeineCache(name, this.cacheBuilder.build(), true); public Collection<String> getCacheNames() {
return Collections.unmodifiableSet(this.cacheMap.keySet());
} }
/** /**
* 缓存配置[缓存容量大小、时长等] * 缓存配置[缓存容量大小、时长等]
* @param caffeineSpec * @param caffeineCacheConfig
*/ */
public void setCaffeineSpec(CaffeineSpec caffeineSpec) { public void setCaffeineCacheConfig(CaffeineSpec caffeineCacheConfig) {
Caffeine<Object, Object> cacheBuilder = Caffeine.from(caffeineSpec); Caffeine<Object, Object> cacheBuilder = Caffeine.from(caffeineCacheConfig);
if (!ObjectUtils.nullSafeEquals(this.cacheBuilder, cacheBuilder)) { if (!ObjectUtils.nullSafeEquals(this.cacheBuilder, cacheBuilder)) {
this.cacheBuilder = cacheBuilder; this.cacheBuilder = cacheBuilder;
refreshKnownCaches();
}
}
/**
* 使用该CacheManager的当前状态重新创建已知的缓存。
*/
private void refreshKnownCaches() {
for (Map.Entry<String, Cache> entry : this.cacheMap.entrySet()) {
entry.setValue(createCache(entry.getKey()));
} }
} }
} }
...@@ -3,97 +3,97 @@ TARGET=PSSYSTEM ...@@ -3,97 +3,97 @@ TARGET=PSSYSTEM
</#ibiztemplate> </#ibiztemplate>
package ${pub.getPKGCodeName()}.util.cache.cacheManager; package ${pub.getPKGCodeName()}.util.cache.cacheManager;
import lombok.Data;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.CaffeineSpec; import com.github.benmanes.caffeine.cache.CaffeineSpec;
import lombok.Data;
import ${pub.getPKGCodeName()}.util.cache.cache.LayeringCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import ${pub.getPKGCodeName()}.util.cache.cache.CusRedisCache;
import ${pub.getPKGCodeName()}.util.cache.cache.LayeringCache;
/** /**
* 缓存分层 * 缓存分层
* 1级缓存为caffeine * 1级缓存为caffeine
* 2级缓存为redis * 2级缓存为redis
*/ */
@Data @Data
@Component
@ConditionalOnExpression("'${r'${ibiz.cacheLevel:None}'}'.equals('L2')")
public class LayeringCacheManager implements CacheManager { public class LayeringCacheManager implements CacheManager {
private static final int DEFAULT_EXPIRE_AFTER_WRITE = 1;
private static final int DEFAULT_INITIAL_CAPACITY = 5;
private static final int DEFAULT_MAXIMUM_SIZE = 1_000;
private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<String, Cache>(16); private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<String, Cache>(16);
public RedisCacheWriter redisCacheWriter; private static final int default_expire_after_write = 1;
public RedisCacheConfiguration redisConfiguration; private static final int default_initial_capacity = 5;
@Autowired private static final int default_maximum_size = 1_000;
public RedisTemplate<String, Object> redisTemplate;
/**
* 缓存默认设置
*/
private Caffeine<Object, Object> cacheBuilder = Caffeine.newBuilder() private Caffeine<Object, Object> cacheBuilder = Caffeine.newBuilder()
.expireAfterAccess(DEFAULT_EXPIRE_AFTER_WRITE, TimeUnit.HOURS) .expireAfterAccess(default_expire_after_write, TimeUnit.HOURS)
.initialCapacity(DEFAULT_INITIAL_CAPACITY) .initialCapacity(default_initial_capacity)
.maximumSize(DEFAULT_MAXIMUM_SIZE); .maximumSize(default_maximum_size);
private RedisCacheWriter redisCacheWriter;
private RedisCacheConfiguration redisConfiguration;
private RedisTemplate<String, Object> redisTemplate;
public LayeringCacheManager(RedisCacheWriter redisCacheWriter , RedisCacheConfiguration redisConfiguration , RedisTemplate<String, Object> redisTemplate ){
this.redisCacheWriter=redisCacheWriter;
this.redisConfiguration=redisConfiguration;
this.redisTemplate= redisTemplate;
}
/** /**
* 获取缓存对象 * 获取缓存对象
* @param name * @param cacheName
* @return * @return
*/ */
@Override @Override
public Cache getCache(String name) { public Cache getCache(String cacheName) {
Cache cache = this.cacheMap.get(name); Cache cache = this.cacheMap.get(cacheName);
if (cache == null) { if (cache == null) {
synchronized (this.cacheMap) { synchronized (this.cacheMap) {
cache = this.cacheMap.get(name); cache = this.cacheMap.get(cacheName);
if (cache == null) { if (cache == null) {
cache = createCache(name); cache = createCache(cacheName);
this.cacheMap.put(name, cache); this.cacheMap.put(cacheName, cache);
} }
} }
} }
return cache; return cache;
} }
/**
* 获取集合中的缓存
* @return
*/
@Override @Override
public Collection<String> getCacheNames() { public Collection<String> getCacheNames() {
return Collections.unmodifiableSet(this.cacheMap.keySet()); return Collections.unmodifiableSet(this.cacheMap.keySet());
} }
protected Cache createCache(String name) {
return new LayeringCache(name,redisTemplate,this.cacheBuilder.build(),redisCacheWriter,redisConfiguration);
}
/** /**
* 使用该CacheManager的当前状态重新创建已知的缓存 * 创建缓存
* @param cacheName
* @return
*/ */
private void refreshKnownCaches() { protected Cache createCache(String cacheName) {
for (Map.Entry<String, Cache> entry : this.cacheMap.entrySet()) { return new LayeringCache(cacheName,new CaffeineCache(cacheName, this.cacheBuilder.build(), true),new CusRedisCache(cacheName, redisCacheWriter, redisConfiguration),redisTemplate);
entry.setValue(createCache(entry.getKey()));
}
} }
public void setCaffeineSpec(CaffeineSpec caffeineSpec) { /**
Caffeine<Object, Object> cacheBuilder = Caffeine.from(caffeineSpec); * 缓存配置[缓存容量大小、时长等]
* @param caffeineCacheConfig
*/
public void setCaffeineCacheConfig(CaffeineSpec caffeineCacheConfig) {
Caffeine<Object, Object> cacheBuilder = Caffeine.from(caffeineCacheConfig);
if (!ObjectUtils.nullSafeEquals(this.cacheBuilder, cacheBuilder)) { if (!ObjectUtils.nullSafeEquals(this.cacheBuilder, cacheBuilder)) {
this.cacheBuilder = cacheBuilder; this.cacheBuilder = cacheBuilder;
refreshKnownCaches();
} }
} }
} }
...@@ -3,39 +3,33 @@ TARGET=PSSYSTEM ...@@ -3,39 +3,33 @@ TARGET=PSSYSTEM
</#ibiztemplate> </#ibiztemplate>
package ${pub.getPKGCodeName()}.util.cache.listener; package ${pub.getPKGCodeName()}.util.cache.listener;
import ${pub.getPKGCodeName()}.util.cache.cache.LayeringCache; import lombok.extern.slf4j.Slf4j;
import ${pub.getPKGCodeName()}.util.enums.RedisChannelTopic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.util.Map; import java.util.Map;
import ${pub.getPKGCodeName()}.util.cache.cache.LayeringCache;
import ${pub.getPKGCodeName()}.util.enums.RedisChannelTopic;
/** /**
* redis消息的订阅者 * redis消息的订阅者
*/ */
@Slf4j
@Component
@ConditionalOnExpression("'${r'${ibiz.cacheLevel:None}'}'.equals('L2')")
public class RedisMessageListener extends MessageListenerAdapter { public class RedisMessageListener extends MessageListenerAdapter {
private static final Logger logger = LoggerFactory.getLogger(RedisPublisher.class); private CacheManager cacheManager;
@Autowired private RedisTemplate redisTemplate;
CacheManager cacheManager;
@Autowired public RedisMessageListener(CacheManager cacheManager, RedisTemplate redisTemplate){
RedisTemplate redisTemplate; this.cacheManager=cacheManager;
this.redisTemplate=redisTemplate;
}
@Override @Override
public void onMessage(Message message, byte[] pattern) { public void onMessage(Message message, byte[] pattern) {
super.onMessage(message, pattern);
RedisChannelTopic channelTopic = RedisChannelTopic.getChannelTopicEnum(new String(message.getChannel())); RedisChannelTopic channelTopic = RedisChannelTopic.getChannelTopicEnum(new String(message.getChannel()));
Map<String, Object> map = null; Map<String, Object> map = null;
RedisSerializer serializer=redisTemplate.getValueSerializer(); RedisSerializer serializer=redisTemplate.getValueSerializer();
...@@ -44,10 +38,10 @@ public class RedisMessageListener extends MessageListenerAdapter { ...@@ -44,10 +38,10 @@ public class RedisMessageListener extends MessageListenerAdapter {
map= (Map<String, Object>) result; map= (Map<String, Object>) result;
} }
if(StringUtils.isEmpty(map)|| (!map.containsKey("cacheName"))|| (!map.containsKey("key"))){ if(StringUtils.isEmpty(map)|| (!map.containsKey("cacheName"))|| (!map.containsKey("key"))){
logger.debug("解析缓存数据失败,无法获取指定值!"); log.debug("解析缓存数据失败,无法获取指定值!");
return ; return ;
} }
logger.debug("redis消息订阅者接收到频道【{}】发布的消息。消息内容:{}", channelTopic.getChannelTopicStr(), result.toString()); log.debug("redis消息订阅者接收到频道【{}】发布的消息。消息内容:{}", channelTopic.getChannelTopicStr(), result.toString());
String cacheName = (String) map.get("cacheName"); String cacheName = (String) map.get("cacheName");
Object key = map.get("key"); Object key = map.get("key");
Cache cache = cacheManager.getCache(cacheName);// 根据缓存名称获取多级缓存 Cache cache = cacheManager.getCache(cacheName);// 根据缓存名称获取多级缓存
...@@ -55,14 +49,16 @@ public class RedisMessageListener extends MessageListenerAdapter { ...@@ -55,14 +49,16 @@ public class RedisMessageListener extends MessageListenerAdapter {
switch (channelTopic) { switch (channelTopic) {
case REDIS_CACHE_DELETE_TOPIC: // 获取一级缓存,并删除一级缓存数据 case REDIS_CACHE_DELETE_TOPIC: // 获取一级缓存,并删除一级缓存数据
((LayeringCache) cache).getFirstCache().evict(key); ((LayeringCache) cache).getFirstCache().evict(key);
logger.debug("删除一级缓存{}数据,key:{},", cacheName, key.toString()); ((LayeringCache) cache).getSecondCache().evict(key);
log.debug("同步删除缓存{}数据,key:{},", cacheName, key.toString());
break; break;
case REDIS_CACHE_CLEAR_TOPIC:// 获取一级缓存,并删除一级缓存数据 case REDIS_CACHE_CLEAR_TOPIC:// 获取一级缓存,并删除一级缓存数据
((LayeringCache) cache).getFirstCache().clear(); ((LayeringCache) cache).getFirstCache().clear();
logger.debug("清除一级缓存{}数据", cacheName); ((LayeringCache) cache).getSecondCache().clear();
log.debug("同步清除缓存{}数据", cacheName);
break; break;
default: default:
logger.debug("接收到没有定义的订阅消息频道数据"); log.debug("接收到没有定义的订阅消息频道数据");
break; break;
} }
} }
......
<#ibiztemplate>
TARGET=PSSYSTEM
</#ibiztemplate>
package ${pub.getPKGCodeName()}.util.cache.redis;
import ${pub.getPKGCodeName()}.util.security.AuthenticationUser;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CustomJacksonSerializer<T> extends Jackson2JsonRedisSerializer<T> {
public static final String DEFAULT_PACKAGE ="[\\w+\\.]+\\.AuthenticationUser";
public static final String USER_PACKAGE= AuthenticationUser.class.getName();
public CustomJacksonSerializer(Class type) {
super(type);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
String serializerContent = new String(bytes, DEFAULT_CHARSET);
Matcher matcher = Pattern.compile(DEFAULT_PACKAGE).matcher(serializerContent);
return matcher.find()?super.deserialize(serializerContent.replaceAll(DEFAULT_PACKAGE,USER_PACKAGE).getBytes()):super.deserialize(bytes);
}
}
...@@ -7,13 +7,10 @@ import org.springframework.data.redis.cache.RedisCache; ...@@ -7,13 +7,10 @@ import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.data.redis.cache.RedisCacheWriter;
/** public class CustomizedRedisCache {
* 自定义的redis缓存
*/
public class CustomizedRedisCache extends RedisCache {
public CustomizedRedisCache(String name, RedisCacheWriter redisCacheWriter,RedisCacheConfiguration configuration) { <#--public CustomizedRedisCache(String name, RedisCacheWriter redisCacheWriter,RedisCacheConfiguration configuration) {-->
super(name, redisCacheWriter, configuration); <#--super(name, redisCacheWriter, configuration);-->
} <#--}-->
} }
...@@ -3,48 +3,42 @@ TARGET=PSSYSTEM ...@@ -3,48 +3,42 @@ TARGET=PSSYSTEM
</#ibiztemplate> </#ibiztemplate>
package ${pub.getPKGCodeName()}.util.cache.redis; package ${pub.getPKGCodeName()}.util.cache.redis;
import com.alibaba.fastjson.JSON; <#--import com.alibaba.fastjson.JSON;-->
import com.alibaba.fastjson.serializer.SerializerFeature; <#--import com.alibaba.fastjson.serializer.SerializerFeature;-->
import org.springframework.data.redis.serializer.RedisSerializer; <#--import org.springframework.data.redis.serializer.RedisSerializer;-->
import org.springframework.data.redis.serializer.SerializationException; <#--import org.springframework.data.redis.serializer.SerializationException;-->
<#--import java.nio.charset.Charset;-->
import java.nio.charset.Charset;
/** public class FastJsonRedisSerializer
* Value 序列化
*
* @author /
* @param <T>
*/
public class FastJsonRedisSerializer<T> implements RedisSerializer<T>
{ {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); <#--public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");-->
private Class<T> clazz; <#--private Class<T> clazz;-->
public FastJsonRedisSerializer(Class<T> clazz) { <#--public FastJsonRedisSerializer(Class<T> clazz) {-->
super(); <#--super();-->
this.clazz = clazz; <#--this.clazz = clazz;-->
} <#--}-->
@Override <#--@Override-->
public byte[] serialize(T t) throws SerializationException <#--public byte[] serialize(T t) throws SerializationException-->
{ <#--{-->
if (t == null) { <#--if (t == null) {-->
return new byte[0]; <#--return new byte[0];-->
} <#--}-->
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); <#--return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);-->
} <#--}-->
@Override <#--@Override-->
public T deserialize(byte[] bytes) throws SerializationException <#--public T deserialize(byte[] bytes) throws SerializationException-->
{ <#--{-->
if (bytes == null || bytes.length <= 0) { <#--if (bytes == null || bytes.length <= 0) {-->
return null; <#--return null;-->
} <#--}-->
String str = new String(bytes, DEFAULT_CHARSET); <#--String str = new String(bytes, DEFAULT_CHARSET);-->
return (T) JSON.parseObject(str, clazz); <#--return (T) JSON.parseObject(str, clazz);-->
} <#--}-->
} }
...@@ -3,72 +3,6 @@ TARGET=PSSYSTEM ...@@ -3,72 +3,6 @@ TARGET=PSSYSTEM
</#ibiztemplate> </#ibiztemplate>
package ${pub.getPKGCodeName()}.util.cache.redis; package ${pub.getPKGCodeName()}.util.cache.redis;
import com.esotericsoftware.kryo.Kryo; public class KryoRedisSerializer{
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.io.ByteArrayOutputStream;
/**
* @param <T>
* 序列化/反序列化工具类
*/
public class KryoRedisSerializer<T> implements RedisSerializer<T> {
Logger logger = LoggerFactory.getLogger(KryoRedisSerializer.class);
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private static final ThreadLocal<Kryo> kryos = ThreadLocal.withInitial(Kryo::new);
private Class<T> clazz;
public KryoRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return EMPTY_BYTE_ARRAY;
}
Kryo kryo = kryos.get();
kryo.setReferences(false);
kryo.register(clazz);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
Output output = new Output(baos)) {
kryo.writeClassAndObject(output, t);
output.flush();
return baos.toByteArray();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return EMPTY_BYTE_ARRAY;
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
Kryo kryo = kryos.get();
kryo.setReferences(false);
kryo.register(clazz);
try (Input input = new Input(bytes)) {
return (T) kryo.readClassAndObject(input);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return null;
}
} }
\ No newline at end of file
...@@ -3,66 +3,6 @@ TARGET=PSSYSTEM ...@@ -3,66 +3,6 @@ TARGET=PSSYSTEM
</#ibiztemplate> </#ibiztemplate>
package ${pub.getPKGCodeName()}.util.cache.redis; package ${pub.getPKGCodeName()}.util.cache.redis;
import com.alibaba.fastjson.JSON; public class RedisConfig {
import com.alibaba.fastjson.parser.ParserConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
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.core.RedisOperations;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
@Slf4j
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig extends CachingConfigurerSupport {
@Value("${r'${spring.cache.redis.time-to-live:3600}'}")
private long timetolive;
/**
* 设置 redis 数据默认过期时间,默认1
* 设置@cacheable 序列化方式
* @return
*/
@Bean
public RedisCacheConfiguration redisCacheConfiguration(){
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofSeconds(timetolive));
return configuration;
}
/**
* 自定义缓存key生成策略
* 使用方法 @Cacheable(keyGenerator="keyGenerator")
* @return
*/
@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) {
// 由于参数可能不同, hashCode肯定不一样, 缓存的key也需要不一样
sb.append(JSON.toJSONString(obj).hashCode());
}
return sb.toString();
};
}
} }
\ No newline at end of file
...@@ -3,44 +3,6 @@ TARGET=PSSYSTEM ...@@ -3,44 +3,6 @@ TARGET=PSSYSTEM
</#ibiztemplate> </#ibiztemplate>
package ${pub.getPKGCodeName()}.util.cache.redis; package ${pub.getPKGCodeName()}.util.cache.redis;
import com.alibaba.fastjson.JSON; public class StringRedisSerializer {
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.util.Assert;
import java.nio.charset.Charset;
/**
* 必须重写序列化器,否则@Cacheable注解的key会报类型转换错误
*/
public class StringRedisSerializer implements RedisSerializer<Object> {
private final Charset charset;
private final String target = "\"";
private final String replacement = "";
public StringRedisSerializer() {
this(Charset.forName("UTF8"));
}
public 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 (string == null) {
return null;
}
string = string.replace(target, replacement);
return string.getBytes(charset);
}
} }
...@@ -8,8 +8,8 @@ import org.springframework.data.redis.listener.ChannelTopic; ...@@ -8,8 +8,8 @@ import org.springframework.data.redis.listener.ChannelTopic;
* redis频道 * redis频道
*/ */
public enum RedisChannelTopic { public enum RedisChannelTopic {
REDIS_CACHE_DELETE_TOPIC("redis:cache:delete:topic", "删除redis缓存消息频道"), REDIS_CACHE_DELETE_TOPIC("redis:cache:delete:topic1", "删除redis缓存消息频道"),
REDIS_CACHE_CLEAR_TOPIC("redis:cache:clear:topic", "清空redis缓存消息频道"); REDIS_CACHE_CLEAR_TOPIC("redis:cache:clear:topic2", "清空redis缓存消息频道");
String channelTopic; String channelTopic;
String label; String label;
......
...@@ -146,14 +146,14 @@ public class AuthenticationUser implements UserDetails ...@@ -146,14 +146,14 @@ public class AuthenticationUser implements UserDetails
return new HashMap<>(); return new HashMap<>();
} }
public Collection<GrantedAuthority> getAuthorities() { public void setPermissionList(JSONObject permissionList) {
this.permissionList = permissionList;
if(authorities==null && permissionList !=null){ if(authorities==null && permissionList !=null){
if(permissionList.getJSONArray("authorities")!=null){ if(permissionList.getJSONArray("authorities")!=null){
authorities=new ArrayList<>(); authorities=new ArrayList<>();
permissionList.getJSONArray("authorities"). permissionList.getJSONArray("authorities").
forEach(item->authorities.add(new SimpleGrantedAuthority(String.valueOf(item)))); forEach(item->authorities.add(new SimpleGrantedAuthority(String.valueOf(item))));
} }
} }
return authorities;
} }
} }
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册