关于在SpringBoot2.0.x版本中集成Redis,我们先看一下官方的迁移文档有什么说的:
Spring Boot2.0迁移指南
当你使用spring-boot-starter-redis的时候,Lettuce现已取代Jedis作为Redis驱动。当你使用更好级别的Spring数据结构时,你会发现变化时清晰的。我们仍然支持Jedis,并且你可以任意切换依赖机制,通过排除io.lettuce:lettuce-core和添加redis.clients.jedis的方式。
Lettuce现已取代Jedis作为Redis驱动。
那Lettuce又是个什么呢?与Jedis又有何区别呢?
Lettuce 是一个可伸缩的线程安全的 Redis 客户端,支持同步、异步和响应式模式。多个线程可以共享一个连接实例,而不必担心多线程并发问题。它基于优秀 Netty NIO 框架构建,支持 Redis 的高级功能,如 Sentinel,集群,流水线,自动重新连接和 Redis 数据模型
Jedis在实现上是直接连接的redis server,如果在多线程环境下是非线程安全的,这个时候只有使用连接池,为每个Jedis实例增加物理连接 Lettuce的连接是基于Netty的,连接实例(StatefulRedisConnection)可以在多个线程间并发访问,应为StatefulRedisConnection是线程安全的,所以一个连接实例(StatefulRedisConnection)就可以满足多线程环境下的并发访问,当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例.
对于SpringBoot集成Redis来说,我们需要导入两个包,即:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-pool2artifactId>
<version>2.4.3version>
dependency>
之后再配置文件中配置与redis有关的属性
spring.redis.host=192.168.31.5
spring.redis.port=6379
spring.redis.password=redis
#连接超时时间(毫秒)
spring.redis.timeout=10000ms
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=16
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池最大阻塞等待时间,单位毫秒(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=1000ms
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0
spring.redis.lettuce.shutdown-timeout=100ms
这样关于redis的属性就配置好了,我们可以测试一下:
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
RedisTemplate redisTemplate;
@Test
public void contextLoads() {
stringRedisTemplate.opsForValue().append("append","asss");
String append = stringRedisTemplate.opsForValue().get("append");
System.out.println(append);
}
@Test
public void test01(){
ValueOperations<String,Object> vo = redisTemplate.opsForValue();
vo.set("redis","redisTemplate");
Object name = vo.get("redis");
System.out.println(name);
}
当然,这一切的前提是你虚拟机中的redis连接成功了,关于在linux中安装启动redis可以参看这篇博客:
Centos 下安装 Redis
这里在配置文件中设置属性时,出现了一个问题:
Value ‘10000’ is not a valid duration
也就是在配置redis连接超时时间时出现的问题,解决方法就是你要在你设置的属性值后面加上单位。
测试完成之后,我们看一下Spring Boot对Redis的自动配置:
按照惯例命名来说,redis的自动配置一般在:RedisAutoConfiguration中。
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
从注解开始看看:
之后可以看出在类中使用@Bean注解声明了两个组件注入到容器中去,分别是stringRedisTemplate
和redisTemplate
,在代码中就是用这两个组件来操作缓存的。
这里还要说下,当你使用stringRedisTemplate
往redis中写入数据的话,你用redisTemplate
是读不到的。因为这两个组件的key与value的序列化方式是不一样的。
进入StringRedisTemplate这个类中可以看一下:
/**
* Constructs a new StringRedisTemplate
instance. {@link #setConnectionFactory(RedisConnectionFactory)}
* and {@link #afterPropertiesSet()} still need to be called.
*/
public StringRedisTemplate() {
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
setKeySerializer(stringSerializer);
setValueSerializer(stringSerializer);
setHashKeySerializer(stringSerializer);
setHashValueSerializer(stringSerializer);
}
可以看到其key与value的序列化是通过StringRedisSerializer实现的。
而RedisTemplate的序列化方式是:
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisAccessor#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
......
其默认的序列化方式是JdkSerializationRedisSerializer。
这里先推荐一款Redis可视化工具:redis-desktop-manager
安装完成打开连接上redis之后,可以看一下之前存放的数据:
可以看到,通过RedisTemplate存放的数据经过JdkSerializationRedisSerializer序列化之后,在redis数据库中呈现的样式有点不符合我们的观感,我们可以修改一下其序列化方式:
首先我们导入一下spring-boot-starter-json这个jar包,这是SpringBoot给我们提供的转化json包,其内部引用了jackson-databind这个jar包.
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jsonartifactId>
dependency>
之后参照StringRedisTemplate新建一个配置文件:
@Configuration
public class RedisTemplateConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 设置值(value)的序列化采用FastJsonRedisSerializer。
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// 设置键(key)的序列化采用StringRedisSerializer。
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
在这里,我们给RedisTemplate的key的序列化方式改为StringRedisSerializer,而value的序列化方式改为GenericJackson2JsonRedisSerializer。
之后继续测试一下:
@Test
public void test01(){
ValueOperations<String,Object> vo = redisTemplate.opsForValue();
// vo.set("redis","redisTemplate");
// Object name = vo.get("redis");
// System.out.println(name);
Student student = new Student(101, "zhangsan", "male");
vo.set("student:"+student.getId(),student);
System.out.println(vo.get("student:"+student.getId()));
}
可以看到,现在使用RedisTemplate存放数据的话,key以String类型存放,value以json类型存放了。
这里在输出的时候System.out.println(vo.get("student:"+student.getId()));
遇到一个异常:
cannot deserialize from Object value (no delegate- or property-based Creator
解决办法就是给实体类添加上无参构造器。
以上就是整个的SpringBoot2.0集成Redis的内容了,完整的代码以及测试内容在GitHub上:spring-boot-redis