Redis-07-SpringBoot整合

Redis-07-SpringBoot整合

SpringBoot 操作数据: Spring-data (jpa,jdbc,mongodb,redis)

1. 整合测试

  1. 新建SpringBoot项目

勾上Starter即可

说明:在SpringBoot2.x之后,Jredis被替换成了lettuce

JRedis: 采用的是直连,是不安全的如果想要避免不安全的,使用jedis pool 连接池!(BIO)

lettuce:采用netty,实例可以在多个线程中共享,不存在线程不安全的情况!可以减少线程数量(NIO)

源码分析:

可以查看RedisAutoConfigure.java和 RedisProperties.java

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
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

@Bean
// 我们可以自己定义RedisTemplate
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
// 默认的没有过多的设置,redis对象都是需要序列化的
// 两个泛型都是object,需要强制转换
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}

@Bean
@ConditionalOnMissingBean
// 由于String类型是最常用的,所以自己单独提出一个Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}

}
  1. 编写配置
1
2
3
4
# 导入配置
spring.redis.host=39.106.171.56
spring.redis.port=6379
spring.redis.password=123456
  1. 测试类中测试链接
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
package com.zhuuu;

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.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class Redis02SpringbootApplicationTests {

@Autowired
private RedisTemplate redisTemplate;

@Test
void contextLoads() {

// 操作各大数据类型
// redisTemplate.opsForList();
// redisTemplate.opsForGeo();
// redisTemplate.opsForHash();
// redisTemplate.opsForValue();

// 获取链接
RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
connection.flushAll();
connection.flushDb();


redisTemplate.opsForValue().set("mykey","zhuuu");
System.out.println(redisTemplate.opsForValue().get("mykey"));

}

}

序列化配置:

2. 测试序列化

json测试

  1. 新建一个pojo/User.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.zhuuu.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {

private String name;
private int age;
}
  1. 测试
1
2
3
4
5
6
7
8
9
@Test
public void test() throws JsonProcessingException {
// 真实的对象一般都使用json来传递对象
User user = new User("朱酱酱", 3);
String jsonUser = new ObjectMapper().writeValueAsString(user);

redisTemplate.opsForValue().set("user",jsonUser);
System.out.println(redisTemplate.opsForValue().get("user"));
}

远程结果显示:(控制台乱码)

1
2
3
127.0.0.1:6379> keys *
1) "\xac\xed\x00\x05t\x00\x05mykey"
2) "\xac\xed\x00\x05t\x00\x04user"

接下来是对象测试:

  1. 测试类
1
2
3
4
5
6
7
    @Test
public void test() throws JsonProcessingException {
User user = new User("朱酱酱", 3);
redisTemplate.opsForValue().set("user",user);
System.out.println(redisTemplate.opsForValue().get("user"));
}
}

结果显示报错:

1
2
3
org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.zhuuu.pojo.User]

at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:96)

对象序列化正确方式

  1. pojo/User.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.zhuuu.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

import java.io.Serializable;

@Component
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User implements Serializable {

private String name;
private int age;
}
  1. 测试类同上
1
2
3
4
5
6
7
    @Test
public void test() throws JsonProcessingException {
User user = new User("朱酱酱", 3);
redisTemplate.opsForValue().set("user",user);
System.out.println(redisTemplate.opsForValue().get("user"));
}
}

结果显示:正常传输

此时Redis默认序列化时会使用JDK序列化器,使得Redis中的key和value值不可读。我们可以改造RedisTemplate,配置自定义序列化器取代默认。

2.1 编写自己的Config

参考博客:https://blog.csdn.net/weixin_41657493/article/details/92851382

固定模板 拿来就用

  1. 新建config/RedisConfig.java
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
package com.zhuuu.config;


import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;


@Configuration
public class RedisConfig {

// 固定的模板,拿来就用
// 编写我们自己的RedisTemplate
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 为了开发方便一般直接使用<String,Object>
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
redisTemplate.setConnectionFactory(redisConnectionFactory);

// json序列化配置使用jackson。
Jackson2JsonRedisSerializer jsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jsonRedisSerializer.setObjectMapper(om);
redisTemplate.setKeySerializer(jsonRedisSerializer);

// String的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

// key采用String的序列化方式
redisTemplate.setKeySerializer(stringRedisSerializer);
// hash的key也采用String方式序列化
redisTemplate.setHashKeySerializer(stringRedisSerializer);
// value的序列化方式采用jackson
redisTemplate.setValueSerializer(jsonRedisSerializer);
// hash value采用jackson序列化方式
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
  1. 测试类测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@SpringBootTest
class Redis02SpringbootApplicationTests {

@Autowired
@Qualifier("redisTemplate")
private RedisTemplate redisTemplate;

@Test
public void test() throws JsonProcessingException {
User user = new User("朱酱酱", 3);

redisTemplate.opsForValue().set("user",user);
System.out.println(redisTemplate.opsForValue().get("user"));
}
}

查看结果:乱码解除

1
2
127.0.0.1:6379> keys *
1) "user"

3. RedisUtils工具类

在真实的开发中,一般都可以在公司看到自己封装的Utils(这里是RedisUtils)

  1. RedisUtils.java
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
package com.zhuuu.Utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
* Redis工具类,使用之前请确保RedisTemplate成功注入
*
*/
@Component
public class RedisUtils {

@Autowired
private RedisTemplate<String,Object> redisTemplate;


/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功;false=设置失败
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit) {

Boolean ret = redisTemplate.expire(key, timeout, unit);
return ret != null && ret;
}

/**
* 删除单个key
*
* @param key 键
* @return true=删除成功;false=删除失败
*/
public boolean del(final String key) {
Boolean ret = redisTemplate.delete(key);
return ret != null && ret;
}

/**
* 删除多个key
*
* @param keys 键集合
* @return 成功删除的个数
*/
public long del(final Collection<String> keys) {

Long ret = redisTemplate.delete(keys);
return ret == null ? 0 : ret;
}

/**
* 存入普通对象
*
* @param key Redis键
* @param value 值
*/
public void set(final String key, final Object value) {

redisTemplate.opsForValue().set(key, value, 1, TimeUnit.MINUTES);
}

// 存储普通对象操作

/**
* 存入普通对象
*
* @param key 键
* @param value 值
* @param timeout 有效期,单位秒
*/
public void set(final String key, final Object value, final long timeout) {

redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
}

/**
* 获取普通对象
*
* @param key 键
* @return 对象
*/
public Object get(final String key) {

return redisTemplate.opsForValue().get(key);
}

// 存储Hash操作

/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value 值
*/
public void hPut(final String key, final String hKey, final Object value) {

redisTemplate.opsForHash().put(key, hKey, value);
}

/**
* 往Hash中存入多个数据
*
* @param key Redis键
* @param values Hash键值对
*/
public void hPutAll(final String key, final Map<String, Object> values) {

redisTemplate.opsForHash().putAll(key, values);
}

/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public Object hGet(final String key, final String hKey) {

return redisTemplate.opsForHash().get(key, hKey);
}

/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public List<Object> hMultiGet(final String key, final Collection<Object> hKeys) {

return redisTemplate.opsForHash().multiGet(key, hKeys);
}

// 存储Set相关操作

/**
* 往Set中存入数据
*
* @param key Redis键
* @param values 值
* @return 存入的个数
*/
public long sSet(final String key, final Object... values) {
Long count = redisTemplate.opsForSet().add(key, values);
return count == null ? 0 : count;
}

/**
* 删除Set中的数据
*
* @param key Redis键
* @param values 值
* @return 移除的个数
*/
public long sDel(final String key, final Object... values) {
Long count = redisTemplate.opsForSet().remove(key, values);
return count == null ? 0 : count;
}

// 存储List相关操作

/**
* 往List中存入数据
*
* @param key Redis键
* @param value 数据
* @return 存入的个数
*/
public long lPush(final String key, final Object value) {
Long count = redisTemplate.opsForList().rightPush(key, value);
return count == null ? 0 : count;
}

/**
* 往List中存入多个数据
*
* @param key Redis键
* @param values 多个数据
* @return 存入的个数
*/
public long lPushAll(final String key, final Collection<Object> values) {
Long count = redisTemplate.opsForList().rightPushAll(key, values);
return count == null ? 0 : count;
}

/**
* 往List中存入多个数据
*
* @param key Redis键
* @param values 多个数据
* @return 存入的个数
*/
public long lPushAll(final String key, final Object... values) {
Long count = redisTemplate.opsForList().rightPushAll(key, values);
return count == null ? 0 : count;
}

/**
* 从List中获取begin到end之间的元素
*
* @param key Redis键
* @param start 开始位置
* @param end 结束位置(start=0,end=-1表示获取全部元素)
* @return List对象
*/
public List<Object> lGet(final String key, final int start, final int end) {
return redisTemplate.opsForList().range(key, start, end);
}
}
  1. 测试类测试Utils
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
package com.zhuuu;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.zhuuu.Utils.RedisUtils;
import com.zhuuu.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class Redis02SpringbootApplicationTests {

@Autowired
@Qualifier("redisTemplate")
private RedisTemplate redisTemplate;

@Autowired
private RedisUtils redisUtils;

@Test
public void testUtils(){
redisUtils.set("mykey","zhuuu");
}
}
打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信