原文博客地址: pjmike的博客html
在实际项目开发过程当中,相信不少人都有用到过 redis 这个NoSQL,这篇文章就详细讲讲springboot如何整合 redisjava
简单介绍下Redis:git
Redis是一个开源的使用 ANSI C语言编写,支持网络,可基于内存也可持久化的日志型,Key-Value数据库,并提供了多种语言的 API ,相比
Memcached
它支持存储的类型相对更多 (字符,哈希,集合,有序集合,列表等),同时Redis是线程安全的。github
在后面 springboot 整合 redis 的时候会用到链接池,因此这里先来介绍下 Redis中的链接池:web
客户端链接 Redis 使用的是 TCP协议,直连的方式每次须要创建 TCP链接,而链接池的方式是能够预先初始化好客户端链接,因此每次只须要从 链接池借用便可,而借用和归还操做是在本地进行的,只有少许的并发同步开销,远远小于新建TCP链接的开销。另外,直连的方式没法限制 redis客户端对象的个数,在极端状况下可能会形成链接泄漏,而链接池的形式能够有效的保护和控制资源的使用。redis
下面以Jedis客户端为例,再来总结下 客户端直连方式和链接池方式的对比spring
优势 | 缺点 | |
---|---|---|
直连 | 简单方便,适用于少许长期链接的场景 | 1. 存在每次新建/关闭TCP链接开销 2. 资源没法控制,极端状况下出现链接泄漏 3. Jedis对象线程不安全(Lettuce对象是线程安全的) |
链接池 | 1. 无需每次链接生成Jedis对象,下降开销 2. 使用链接池的形式保护和控制资源的使用 | 相对于直连,使用更加麻烦,尤为在资源的管理上须要不少参数来保证,一旦规划不合理也会出现问题 |
redis官方提供的java client有如图所示几种: sql
Lettuce 是 一种可伸缩,线程安全,彻底非阻塞的Redis客户端,多个线程能够共享一个RedisConnection,它利用Netty NIO 框架来高效地管理多个链接,从而提供了异步和同步数据访问方式,用于构建非阻塞的反应性应用程序。数据库
在 springboot 1.5.x版本的默认的Redis客户端是 Jedis
实现的,springboot 2.x版本中默认客户端是用 lettuce
实现的。segmentfault
下面介绍 springboot 2.0
分别使用 jedis
和 lettuce
集成 redis服务
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
复制代码
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=root
# 链接池最大链接数(使用负值表示没有限制) 默认为8
spring.redis.lettuce.pool.max-active=8
# 链接池最大阻塞等待时间(使用负值表示没有限制) 默认为-1
spring.redis.lettuce.pool.max-wait=-1ms
# 链接池中的最大空闲链接 默认为8
spring.redis.lettuce.pool.max-idle=8
# 链接池中的最小空闲链接 默认为 0
spring.redis.lettuce.pool.min-idle=0
复制代码
默认状况下的模板只能支持 RedisTemplate<String,String>
,只能存入字符串,不少时候,咱们须要自定义 RedisTemplate ,设置序列化器,这样咱们能够很方便的操做实例对象。以下所示:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory connectionFactory) {
RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
}
复制代码
public class User implements Serializable {
private static final long serialVersionUID = 4220515347228129741L;
private Integer id;
private String username;
private Integer age;
public User(Integer id, String username, Integer age) {
this.id = id;
this.username = username;
this.age = age;
}
public User() {
}
//getter/setter 省略
}
复制代码
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
private Logger logger = LoggerFactory.getLogger(RedisTest.class);
@Autowired
private RedisTemplate<String, Serializable> redisTemplate;
@Test
public void test() {
String key = "user:1";
redisTemplate.opsForValue().set(key, new User(1,"pjmike",20));
User user = (User) redisTemplate.opsForValue().get(key);
logger.info("uesr: "+user.toString());
}
}
复制代码
由于 springboot2.0中默认是使用 Lettuce来集成Redis服务,spring-boot-starter-data-redis
默认只引入了 Lettuce
包,并无引入 jedis
包支持。因此在咱们须要手动引入 jedis
的包,并排除掉 lettuce
的包,pom.xml配置以下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
复制代码
使用jedis的链接池
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=root
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.max-wait=-1ms
spring.redis.jedis.pool.min-idle=0
spring.redis.jedis.pool.max-active=8
复制代码
由于在 springoot 2.x版本中,默认采用的是 Lettuce实现的,因此没法初始化出 Jedis的链接对象 JedisConnectionFactory
,因此咱们须要手动配置并注入:
public class RedisConfig {
@Bean
JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
return factory;
}
复制代码
可是启动项目后发现报出了以下的异常:
redis链接失败,springboot2.x经过以上方式集成Redis并不会读取配置文件中的 spring.redis.host
等这样的配置,须要手动配置,以下:
@Configuration
public class RedisConfig2 {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Bean
public RedisTemplate<String, Serializable> redisTemplate(JedisConnectionFactory connectionFactory) {
RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(jedisConnectionFactory());
return redisTemplate;
}
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPort(port);
config.setPassword(RedisPassword.of(password));
JedisConnectionFactory connectionFactory = new JedisConnectionFactory(config);
return connectionFactory;
}
}
复制代码
经过以上方式就能够链接上 redis了,不过这里要提醒的一点就是,在springboot 2.x版本中 JedisConnectionFactory
设置链接的方法已过期,如图所示:
在 springboot 2.x
版本中推荐使用 RedisStandaloneConfiguration
类来设置链接的端口,地址等属性
而后是单元测试,与上面 Lettuce
的例子代码同样,而且测试经过。
上面介绍springboot 2.x版本如何经过 Jedis 和 Lettuce 来集成Redis服务,源代码地址以下:github.com/pjmike/spri…