Spring Boot项目缓存配置(未测试,未完善)
1、你需要准备和配置的事情
引入依赖
<!-- Redis数据库 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
基础配置
#缓存策略相关配置
spring.cache.type=REDIS
spring.cache.redis.time-to-live=600000
#Redis缓存数据库配置
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.jedis.pool.max-active=8
#这个是自定义的标识,用于指定Redis的消息通道名
springext.cache.redis.channel=cache
2、基于ConcurrentHashMap和Redis的两级缓存管理器
package com.drsanjun.cache;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
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.core.RedisTemplate;
/**
* 基于ConcurrentHashMap和Redis的两级缓存管理器
*
* @author dyw
* @date 2019年9月30日
*/
@SuppressWarnings("rawtypes")
public class TwoLevelCacheManager extends RedisCacheManager {
@Value("springext.cache.redis.channel")
private String topicName;
/**
* Redis缓存数据库访问工具
*/
private RedisTemplate redisTemplate;
/**
*
* @param redisTemplate
* @param cacheWriter
* @param defaultCacheConfiguration
*/
public TwoLevelCacheManager(RedisTemplate redisTemplate, RedisCacheWriter cacheWriter,
RedisCacheConfiguration defaultCacheConfiguration) {
super(cacheWriter, defaultCacheConfiguration);
this.redisTemplate = redisTemplate;
}
@Override
protected Cache decorateCache(Cache cache) {
return new RedisAndLocalCache(this, (RedisCache) cache);
}
/**
*
* @param channel
* @param cacheName
*/
public void publishMessage(String cacheName) {
this.redisTemplate.convertAndSend(topicName, cacheName);
}
/**
*
* @param name
*/
public void receiver(String name) {
RedisAndLocalCache cache = (RedisAndLocalCache) this.getCache(name);
if (cache != null) {
cache.clearLocal();
}
}
}
3、基于ConcurrentHashMap和Redis的两级缓存器
package com.drsanjun.cache;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.cache.Cache;
import org.springframework.data.redis.cache.RedisCache;
/**
* 基于ConcurrentHashMap和Redis的两级缓存器
*
* @author dyw
* @date 2019年9月30日
*/
public class RedisAndLocalCache implements Cache {
private ConcurrentHashMap<Object, Object> local = new ConcurrentHashMap<>();
private RedisCache redisCache;
private TwoLevelCacheManager cacheManager;
public RedisAndLocalCache(TwoLevelCacheManager redisCacheManager, RedisCache cache) {
this.redisCache = cache;
this.cacheManager = redisCacheManager;
}
@Override
public String getName() {
return redisCache.getName();
}
@Override
public Object getNativeCache() {
return redisCache.getNativeCache();
}
@Override
public ValueWrapper get(Object key) {
ValueWrapper wrapper = (ValueWrapper) local.get(key);
if (wrapper == null) {
return wrapper;
} else {
wrapper = redisCache.get(key);
if (wrapper != null) {
local.put(key, wrapper);
}
return wrapper;
}
}
@Override
public void put(Object key, Object value) {
redisCache.put(key, value);
clearOtherJVM();
}
@Override
public void evict(Object key) {
redisCache.evict(key);
clearOtherJVM();
}
@Override
public <T> T get(Object key, Class<T> type) {
return redisCache.get(key, type);
}
@Override
public <T> T get(Object key, Callable<T> valueLoader) {
return redisCache.get(key, valueLoader);
}
@Override
public ValueWrapper putIfAbsent(Object key, Object value) {
return redisCache.putIfAbsent(key, value);
}
@Override
public void clear() {
redisCache.clear();
}
protected void clearOtherJVM() {
cacheManager.publishMessage(redisCache.getName());
}
public void clearLocal() {
this.local.clear();
}
}
4、缓存配置
package com.drsanjun.configuration;
import java.io.UnsupportedEncodingException;
import org.springframework.beans.factory.annotation.Value;
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.RedisCacheWriter;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair;
import com.drsanjun.cache.TwoLevelCacheManager;
/**
* 缓存配置
*
* @author dyw
* @date 2019年9月30日
*/
@Configuration
@SuppressWarnings("rawtypes")
public class CacheConfig {
@Value("springext.cache.redis.channel")
private String topicName;
public TwoLevelCacheManager cacheManager(StringRedisTemplate redisTemplate) {
RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(redisTemplate.getConnectionFactory());
SerializationPair pair = SerializationPair
.fromSerializer(new JdkSerializationRedisSerializer(this.getClass().getClassLoader()));
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
return new TwoLevelCacheManager(redisTemplate, writer, config);
}
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic(topicName));
return container;
}
@Bean
MessageListenerAdapter listenerAdapter(final TwoLevelCacheManager cacheManager) {
return new MessageListenerAdapter(new MessageListener() {
@Override
public void onMessage(Message message, byte[] pattern) {
try {
String cacheName = new String(message.getBody(), "UTF-8");
cacheManager.receiver(cacheName);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
});
}
}