SpringBoot整合Redis
# SpringBoot整合Redis
SpringBoot (opens new window) 操作数据:spring-data jpa. jdbc. mongodb. redis!
SpringData (opens new window) 也是和 SpringBoot 齐名的项目!
说明: 在 SpringBoot2.x 之后,客户端原来使用的jedis 被替换为了 lettuce?
jedis :
采用的直连
,多个线程操作的话,是不安全的
,如果想要避免不安全的,使用 jedis pool 连接池! 更像 BIO 模式.lettuce :
采用netty
,实例可以再多个线程中进行共享,不存在线程不安全的情况!可以减少线程数据了
,更像 NIO 模式.
# 1. 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
1
2
3
4
2
3
4
springboot版本
2.x
使用的是lettce
- 上边集成boot的依赖所包含的核心包
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.2.5.RELEASE</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>jcl-over-slf4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>5.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
当在配置文件application.properties
配置 lettuce
时,启动项目出现
Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.GenericObjectPoolConfig
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 93 more
1
2
3
4
5
6
2
3
4
5
6
解决: pxm.xml
配置
<!--redis客户端Lettuce 数据库连接池依赖 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
1
2
3
4
5
2
3
4
5
# 2. 配置
# 2.1 redis配置类[源码]
- RedisAutoConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
// RedisTemplate
@Bean
// 我们可以自己定义一个 redisTemplate来替换这个默认的!
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
// 默认的 RedisTemplate 没有过多的设置,redis 对象都是需要序列化!
// 两个泛型都是 Object, Object 的类型,我们后使用需要强制转换 <String, Object>
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
// StringRedisTemplate
@Bean
// 由于 String 是redis中最常使用的类型,所以说单独提出来了一 个bean!
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@ConditionalOnMissingBean
: 当这个Bean不存在式,这个类生效
- RedisProperties:
redis默认配置
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
private int database = 0;
private String url;
private String host = "localhost";
private String password;
private int port = 6379;
private boolean ssl;
private Duration timeout;
private String clientName;
private Sentinel sentinel;
private Cluster cluster;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 2.2 配置文件
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接超时时间
spring.redis.timeout=10000ms
# 这里使用 lettuce
# 连接池最大连接数
spring.redis.lettuce.pool.max-active=1000
# 连接池最大阻塞等待时间
spring.redis.lettuce.pool.max-wait=-1ms
# 连接池最大空闲连接
spring.redis.lettuce.pool.max-idle=10
#连接池最小空闲连接
spring.redis.lettuce.pool.min-idle=5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
此处使用
.properties
形式配置
# 3 测试
# 3.1 乱码
@Resource
private RedisTemplate redisTemplate;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Test
void contextLoads() {
redisTemplate.opsForValue().set("key01", "Hello Redis !");
stringRedisTemplate.opsForValue().set("key02", "Hello Redis !");
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
127.0.0.1:6379> keys *
1) "key02"
2) "\xac\xed\x00\x05t\x00\x05key01"
1
2
3
2
3
redisTemplate
: 出现中文乱码
# 3.2 对象保存需要序列化
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private Integer age;
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
// User实体类,未序列化
User user = new User("chggx", 3);
redisTemplate.opsForValue().set("user",user);
1
2
3
2
3
结果:
解决: 在 User
中添加序列化 implements Serializable
127.0.0.1:6379> keys *
1) "\xac\xed\x00\x05t\x00\x04user"
1
2
2
# 4. redis序列化配置
- RedisTemplate
# 4.1 自定义redis配置类
@Configuration
public class RedisConfig {
/**
* Redis连接工厂
*/
@Autowired
private RedisConnectionFactory redisConnectionFactory;
/**
* String 的序列化
*
* @return
*/
@Bean
public RedisSerializer<String> stringRedisSerializer() {
return new StringRedisSerializer();
}
/**
* Jackson2JsonRedisSerializer序列化
*
* @return
*/
@Bean
public Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
return jackson2JsonRedisSerializer;
}
/**
* RedisTemplate
*
* @return
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate() {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
// Redis连接工厂
template.setConnectionFactory(redisConnectionFactory);
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer());
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer());
// value序列化方式采用
template.setValueSerializer(jackson2JsonRedisSerializer());
// hash的value序列化方式采用
template.setHashValueSerializer(jackson2JsonRedisSerializer());
template.afterPropertiesSet();
// 开启事务支持
template.setEnableTransactionSupport(true);
return template;
}
/**
* StringRedisTemplate
*
* @param redisConnectionFactory
* @return
*/
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
// Redis连接工厂
template.setConnectionFactory(redisConnectionFactory);
// 开启事务支持
template.setEnableTransactionSupport(true);
return template;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
3.2
中结果,经过redisjson序列化
后
127.0.0.1:6379> keys *
1) "user"
127.0.0.1:6379> get user
"[\"com.chggx.pojo.User\",{\"name\":\"chggx\",\"age\":3}]"
1
2
3
4
2
3
4
# 4.2 自定义redis工具类
自定义Redis配置类
链接:https://pan.baidu.com/s/1mVAi1-yG7fA2Y-hTwEzp5g 提取码:fp92
- 测试
/**
* 自定义缓存类
*/
@Autowired
private RedisUtil redisUtil;
@Test
void test03(){
// 设置
redisUtil.set("name","chggx");
// 获取
System.out.println(redisUtil.get("name"));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
上次更新: 2023/03/27, 08:56:25