1.前言
项目中用到缓存是很常见的事情, 缓存能够提升系统访问的速度,减轻对数据库的压力等好处。Java Web项目通常会引入NoSQL技术,这是一种基于内存的数据库,并且提供一定的持久化功能。
就Redis技术而言,它的性能十分优越,可以支持每秒十几万此的读/写操作,其性能远超数据库,并且还支持集群、分布式、主从同步等配置,原则上可以无限扩展,让更多的数据存储在内存中,更让人欣慰的是它还支持一定的事务能力,这保证了高并发的场景下数据的安全和一致性。
今天我们来讲讲怎么在spring boot 中整合redis 实现对数据库查询结果的缓存。
2.引入Redis
首先第一步要做的就是在pom.xml文件添加spring-boot-starter-data-redis。
要整合缓存,必不可少的就是我们要继承一个父类CachingConfigurerSupport。我们先看看这个类的源码
public class CachingConfigurerSupport implements CachingConfigurer {
// Spring's central cache manage SPI ,
@Override
@Nullable
public CacheManager cacheManager() {
return null;
}
//key的生成策略
@Override
@Nullable
public KeyGenerator keyGenerator() {
return null;
}
//Determine the Cache instance(s) to use for an intercepted method invocation.
@Override
@Nullable
public CacheResolver cacheResolver() {
return null;
}
//缓存错误处理
@Override
@Nullable
public CacheErrorHandler errorHandler() {
return null;
}
}
3.配置RedisConfig类
RedisConfig类
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("chat"));
return container;
}
@Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
@Bean
Receiver receiver(CountDownLatch latch) {
return new Receiver(latch);
}
@Bean
CountDownLatch latch() {
return new CountDownLatch(1);
}
public class Receiver {
private CountDownLatch latch;
@Autowired
public Receiver(CountDownLatch latch) {
this.latch = latch;
}
public void receiveMessage(String message) {
latch.countDown();
}
}
@Bean
public KeyGenerator myKeyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... objects) {
StringBuilder sb = new StringBuilder();
sb.append(o.getClass().getName());
sb.append(method.getName());
for (Object obj : objects) {
sb.append(JSON.toJSONString(obj));
}
return sb.toString();
}
};
}
/**
* @param redisConnectionFactory
* @return
* @// TODO: 2018/4/27 redis fastjson序列化
*/
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//使用fastjson序列化
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
// 全局开启AutoType,不建议使用
// ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
// 建议使用这种方式,小范围指定白名单
ParserConfig.getGlobalInstance().addAccept("com.developlee.models.");
// value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
// key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean(StringRedisTemplate.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
/**
* @return
* @// TODO: 2018/4/27 设置redis 缓存时间 5 分钟
*/
@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofMinutes(5));
return configuration;
}
}
这段代码中,重点关注对象是RedisTemplate 和StringRedisTemplate还有RedisMessageListenerContainer,RedisTemplate和StringRedisTemplate设置了一些序列化的参数和指定序列化的范围(主要为了防止黑客利用Redis的序列化漏洞),@ConditionalOnMissingBean注解的意思就是如果容器中没有这个类型Bean就选择当前Bean。RedisMessageListenerContainer是为Redis消息侦听器提供异步行为的容器,主要处理低层次的监听、转换和消息发送的细节。
4.配置application.xml
再来看看application.xml我们的配置 , so easy~~
spring:
redis:
database: 0 # Redis数据库索引(默认为0)
host: 192.168.0.100 # Redis服务器地址 (默认为127.0.0.1)
port: 6379 # Redis服务器连接端口 (默认为6379)
password: 123456 # Redis服务器连接密码(默认为空)
timeout: 2000 # 连接超时时间(毫秒)
cache:
type: redis
5.使用注解使用缓存
接下来我们就可以使用Redis缓存了,在Service层我们用注解@Cacheable来缓存查询的结果。
@Cacheable(value= "orderDetailCache", keyGenerator = "myKeyGenerator", unless = "#result eq null")
public OrderDetailEntity findOrderDetail(OrderDetailEntity orderDetailEntity) {
return orderDetailDao.findEntity(orderDetailEntity);
}
到这里我们就已经整合了Redis缓存了,是不是很简单的呢?自己多动手尝试哦!
上一篇文章:精通Spring Boot : 整合druid监控SQL执行
最后,以上示例代码可在我的github.com中找到。
[…] 上一篇教程:精通Spring Boot:整合Redis实现缓存 […]