SpringBoot整合Redis
本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Redis是现在最流行的nosql(非关系型数据库)了,因为它是在内存上操作,所以速度快,非常受大家青睐,今天讲讲如何在SpringBoot里整合Redis。
Redis
首先确认自己电脑上有Redis,是不是能见到这个东西呢
如果能用redis的可视化工具RedisDesktopManager查看一下就更稳妥不过,关于RedisDesktopManager的安装和使用可以看我这篇文章。
前言
1、Redis在实际应用面很广,可以做缓存、消息队列等。
2、目前流行的Redis集成到Java环境有两种方案,分别是Jedis和lettuce。老版本中Jedis用的比较多,但是在SpringBoot2.x后官方已经推荐默认lettuce连接了。原因主要是,Jedis虽然线程安全,但占用资源较大,而lettuce基于netty和nio相关实现,性能不但强,而且占用资源更少。
3、我们知道Redis有16个分区(表),如果不配置默认用0号库(第一个)。
4、Redis的默认五个基本类型:String、set、hash、zset(有序集合)、list
5、Spring中的的Redis数据封装有StringRedisTemplate和RedisTemplate
RedisTemplate和StringRedisTemplate的区别:
-
两者的关系是StringRedisTemplate继承RedisTemplate。
-
两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。
-
SDR默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。
StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。(JdkSerializationRedisSerializer)
RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。(StringRedisSerializer)
6、如果Redis要操作对象,pojo一定要序列化(Serializer)。否则不能和Redis交互。
开始整合
创建新项目
创建一个新的SpringBoot项目
创建时选择Redis依赖,或者创建后导入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
添加缓存池依赖(如果不配置连接池大小、连接数等可不添加)
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId> commons-pool2</artifactId>
</dependency>
编写配置文件
application.properties
#SpringBoot所有的配置类,都有一个自动配置类 RedisAutoConfiguration
#自动配置类会绑定一个properties配置文件 RedisProperties
#配置Redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
#密码没有就不写
spring.redis.timeout=10000
#设置超时
spring.cache.type=redis
#将redis设置为缓存
# Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
spring.redis.database=1
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0
测试连接
在SpringBootTest类中
@SpringBootTest
class SpringbootRedisTestApplicationTests {
@Autowired
RedisTemplate redisTemplate;
@Test
void contextLoads() {
System.out.println(redisTemplate.execute(RedisConnectionCommands::ping));
}
}
记得启动Redis先啊亲
创建RedisConfig类
为什么SpringBoot有我们还要创建?我们看看自带的RedisAutoConfiguration
可以看到SpringBoot帮我们在容器中生成了两个封装对象,一个是RedisTemplate,还有一个是StringRedisTemplate。但是这个RedisTemplate是<Object,Object>的,显然用的不舒服,我们可以自己整个自定义的配置类来配置RedisTemplate。后面我们也可以测试用自带的和我们自定义的区别。
RedisConfiguration.java
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Serializable> template = new RedisTemplate<>();
GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 设置键(key)的序列化采用StringRedisSerializer。
template.setKeySerializer(new StringRedisSerializer());
// 设置值(value)的序列化采用jackson的序列化。
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
创建实体类
User.java
package com.feng.springbootredistest.pojo;
import java.io.Serializable;
/**
* <h3>springboot-redis-test</h3>
* <p></p>
*
* @author : Nicer_feng
* @date : 2020-10-07 19:23
**/
public class User implements Serializable {
private Integer id;
private String name;
private String pwd;
public User(Integer id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
测试
在SpringBootTest中测试我们的模板
package com.feng.springbootredistest;
import com.feng.springbootredistest.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.RedisConnectionCommands;
import org.springframework.data.redis.core.RedisTemplate;
@SpringBootTest
class SpringbootRedisTestApplicationTests {
@Autowired
RedisTemplate redisTemplate;
@Autowired
RedisTemplate redisCacheTemplate;
@Test
void contextLoads() {
System.out.println(redisTemplate.execute(RedisConnectionCommands::ping));
}
@Test
public void queryUser1(){
Object user = redisCacheTemplate.opsForValue().get("feng");
if(user!=null){
System.out.println((User) user+" 数据在缓存中读到");
}else{
//假装去了数据库
User userFromMysql = new User(1,"feng1","111111");
redisCacheTemplate.opsForValue().set("feng",userFromMysql);
System.out.println(userFromMysql+" 从数据库里拿到并存入redis缓存中");
}
}
@Test
public void queryUser0(){
Object user = redisTemplate.opsForValue().get("feng");
if(user!=null){
System.out.println((User) user+" 数据在缓存中读到");
}else{
User userFromMysql = new User(1,"feng0","000000");
redisTemplate.opsForValue().set("feng",userFromMysql);
System.out.println(userFromMysql+" 从数据库里拿到并存入redis缓存中");
}
}
}
我们这里写了两个test,一个是我们自己封装的Template,一个是SpringBoot自带的,分别使用,看看有什么不同。
SpringBoot自带Template
自定义的RedisTemplate
怎么样,看出区别了吧。主要是我们的json字符串传输问题,代码里我也模拟了redis作为缓存的实际业务情况,controller层的业务也不再赘述,讲到这里基本没啥区别。到这里整合基本结束了。
附
-
推荐使用RedisDesktopManager可视化工具实时观察redis内的情况
-
实体类记得序列化
-
如果不想配置序列化可以直接使用自带的,但是不利于观察!虽然不影响存取
-
推荐使用自定义RedisTemplate模板