当前位置: 首页 >Java技术 > SpringBoot整合Redis缓存

SpringBoot整合Redis缓存

一、前言

之前分享过关于Redis集群如何搭建的,最近有小伙伴儿说分享一下Redis如何使用SpringBoot的整合,项目中经常使用的就是Redis,本次整合的是Redis单机版,后续会分享Redis集群版本,请多提出自己的意见。

二、开始整合

1.首先需要搭建Redis服务器,可参考之前的博客()

2019/04/26/Redis的搭建(win和linux版)

2.搭建SpringBoot工程,参考之前的博客

SpringBoot工程搭建

3.在pom文件加入redis的依赖和Json相关依赖

1
2
3
4
5
6
7
8
9
10
<!-- Redis 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>

4.创建项目结构,结构如下图所示

SpringBoot整合Redis缓存 _ JavaClub全栈架构师技术笔记

5.项目全局配置文件application.properties文件配置Redis的相关配置

如下问全部的配置,因为我的redis没有设置密码,故password被我注释掉了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#项目启动端口
server.port=8088
#应用上下文
server.context-path = /SpringBootRedis
#redis相关配置
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
#spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=10
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=1000

6.配置redis的配置文件,使用RedisTemplate进行操作,需要将数据的进行序列化,才不会出现乱码

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
package com.yang.config.redis;

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;

/**
* Redis配置类
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
retu template;
}
}

7.编写redis工具类,供开发使用,注入RedisTemplate进行操作

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.yang.config.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.concurrent.TimeUnit;

/**
* redis 工具,存取
*/
@Configuration
public class RedisUtil {

@Autowired
private RedisTemplate<String,Object> redisTemplate;

/**
* 存数据
* @param key
* @param value
*/
public void set(String key , Object value){
redisTemplate.opsForValue().set(key,value);
}

/**
* 存数据
* @param key 键
* @param value 值
* @param exp 过期时间 默认秒
* @param s 使用 时还是分还是秒,默认秒
*/
public void set(String key , Object value , int exp,TimeUnit s){
if( s==null ){
s = TimeUnit.SECONDS;
}
redisTemplate.opsForValue().set(key,value,exp, s);
}

/**
* 获取数据
* @param key
* @retu
*/
public <T>T get(String key){
retu (T)redisTemplate.opsForValue().get(key);
}

}

8.编写RedisController,编写set和get,使用请求来存储redis的值和获取redis的值

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
package com.yang.controller;

import com.yang.config.redis.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/redis")
public class RedisController {

@Autowired
private RedisUtil redisUtil;

/**
* redis测试
* @retu
*/
@GetMapping("/get")
public String get(@RequestParam(value="key") String key){
retu redisUtil.get(key).toString();
}
/**
* redis测试
* @retu
*/
@GetMapping("/put")
public String put(@RequestParam(value="key") String key,@RequestParam(value="value") String value){
redisUtil.set(key,value);
retu "success";
}
}

9.使用浏览器访问接口保存数据,并查询数据

SpringBoot整合Redis缓存 _ JavaClub全栈架构师技术笔记

SpringBoot整合Redis缓存 _ JavaClub全栈架构师技术笔记

三、加载机制剖析

1.经过查看,Redis的包中,包含RedisAutoConfiguration这个配置类,使用了Configuration注解,SpringBoot会自动加载

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
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Feflower decompiler)
//

package org.springframework.boot.autoconfigure.data.redis;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Cluster;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Pool;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Sentinel;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;

@Configuration
@ConditionalOnClass({JedisConnection.class, RedisOperations.class, Jedis.class})
@EnableConfigurationProperties({RedisProperties.class})
public class RedisAutoConfiguration {
public RedisAutoConfiguration() {
}

@Configuration
protected static class RedisConfiguration {
protected RedisConfiguration() {
}

@Bean
@ConditionalOnMissingBean(
name = {"redisTemplate"}
)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
retu template;
}

@Bean
@ConditionalOnMissingBean({StringRedisTemplate.class})
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
retu template;
}
}

@Configuration
@ConditionalOnClass({GenericObjectPool.class})
protected static class RedisConnectionConfiguration {
private final RedisProperties properties;
private final RedisSentinelConfiguration sentinelConfiguration;
private final RedisClusterConfiguration clusterConfiguration;

public RedisConnectionConfiguration(RedisProperties properties, ObjectProvider<RedisSentinelConfiguration> sentinelConfiguration, ObjectProvider<RedisClusterConfiguration> clusterConfiguration) {
this.properties = properties;
this.sentinelConfiguration = (RedisSentinelConfiguration)sentinelConfiguration.getIfAvailable();
this.clusterConfiguration = (RedisClusterConfiguration)clusterConfiguration.getIfAvailable();
}

@Bean
@ConditionalOnMissingBean({RedisConnectionFactory.class})
public JedisConnectionFactory redisConnectionFactory() throws UnknownHostException {
retu this.applyProperties(this.createJedisConnectionFactory());
}

protected final JedisConnectionFactory applyProperties(JedisConnectionFactory factory) {
this.configureConnection(factory);
if (this.properties.isSsl()) {
factory.setUseSsl(true);
}

factory.setDatabase(this.properties.getDatabase());
if (this.properties.getTimeout() > 0) {
factory.setTimeout(this.properties.getTimeout());
}

retu factory;
}

private void configureConnection(JedisConnectionFactory factory) {
if (StringUtils.hasText(this.properties.getUrl())) {
this.configureConnectionFromUrl(factory);
} else {
factory.setHostName(this.properties.getHost());
factory.setPort(this.properties.getPort());
if (this.properties.getPassword() != null) {
factory.setPassword(this.properties.getPassword());
}
}

}

private void configureConnectionFromUrl(JedisConnectionFactory factory) {
String url = this.properties.getUrl();
if (url.startsWith("rediss://")) {
factory.setUseSsl(true);
}

try {
URI uri = new URI(url);
factory.setHostName(uri.getHost());
factory.setPort(uri.getPort());
if (uri.getUserInfo() != null) {
String password = uri.getUserInfo();
int index = password.lastIndexOf(":");
if (index >= 0) {
password = password.substring(index + 1);
}

factory.setPassword(password);
}

} catch (URISyntaxException var6) {
throw new IllegalArgumentException("Malformed 'spring.redis.url' " + url, var6);
}
}

protected final RedisSentinelConfiguration getSentinelConfig() {
if (this.sentinelConfiguration != null) {
retu this.sentinelConfiguration;
} else {
Sentinel sentinelProperties = this.properties.getSentinel();
if (sentinelProperties != null) {
RedisSentinelConfiguration config = new RedisSentinelConfiguration();
config.master(sentinelProperties.getMaster());
config.setSentinels(this.createSentinels(sentinelProperties));
retu config;
} else {
retu null;
}
}
}

protected final RedisClusterConfiguration getClusterConfiguration() {
if (this.clusterConfiguration != null) {
retu this.clusterConfiguration;
} else if (this.properties.getCluster() == null) {
retu null;
} else {
Cluster clusterProperties = this.properties.getCluster();
RedisClusterConfiguration config = new RedisClusterConfiguration(clusterProperties.getNodes());
if (clusterProperties.getMaxRedirects() != null) {
config.setMaxRedirects(clusterProperties.getMaxRedirects().intValue());
}

retu config;
}
}

private List<RedisNode> createSentinels(Sentinel sentinel) {
List<RedisNode> nodes = new ArrayList();
String[] var3 = StringUtils.commaDelimitedListToStringArray(sentinel.getNodes());
int var4 = var3.length;

for(int var5 = 0; var5 < var4; ++var5) {
String node = var3[var5];

try {
String[] parts = StringUtils.split(node, ":");
Assert.state(parts.length == 2, "Must be defined as 'host:port'");
nodes.add(new RedisNode(parts[0], Integer.valueOf(parts[1]).intValue()));
} catch (RuntimeException var8) {
throw new IllegalStateException("Invalid redis sentinel property '" + node + "'", var8);
}
}

retu nodes;
}

private JedisConnectionFactory createJedisConnectionFactory() {
JedisPoolConfig poolConfig = this.properties.getPool() != null ? this.jedisPoolConfig() : new JedisPoolConfig();
if (this.getSentinelConfig() != null) {
retu new JedisConnectionFactory(this.getSentinelConfig(), poolConfig);
} else {
retu this.getClusterConfiguration() != null ? new JedisConnectionFactory(this.getClusterConfiguration(), poolConfig) : new JedisConnectionFactory(poolConfig);
}
}

private JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig config = new JedisPoolConfig();
Pool props = this.properties.getPool();
config.setMaxTotal(props.getMaxActive());
config.setMaxIdle(props.getMaxIdle());
config.setMinIdle(props.getMinIdle());
config.setMaxWaitMillis((long)props.getMaxWait());
retu config;
}
}
}

2.配置了EnableConfigurationProperties,配置了RedisProperties,而RedisProperties则使用了ConfigurationProperties,加载了前缀为spring.redis的所有配置,故读取了application.properties文件中的内容。

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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language goveing permissions and
* limitations under the License.
*/

package org.springframework.boot.autoconfigure.data.redis;

import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
* Configuration properties for Redis.
*
* @author Dave Syer
* @author Christoph Strobl
* @author Eddú Meléndez
* @author Marco Aust
*/
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {

/**
* Database index used by the connection factory.
*/
private int database = 0;

/**
* Redis url, which will overrule host, port and password if set.
*/
private String url;

/**
* Redis server host.
*/
private String host = "localhost";

/**
* Login password of the redis server.
*/
private String password;

/**
* Redis server port.
*/
private int port = 6379;

/**
* Enable SSL.
*/
private boolean ssl;

/**
* Connection timeout in milliseconds.
*/
private int timeout;

private Pool pool;

private Sentinel sentinel;

private Cluster cluster;

public int getDatabase() {
retu this.database;
}

public void setDatabase(int database) {
this.database = database;
}

public String getUrl() {
retu this.url;
}

public void setUrl(String url) {
this.url = url;
}

public String getHost() {
retu this.host;
}

public void setHost(String host) {
this.host = host;
}

public String getPassword() {
retu this.password;
}

public void setPassword(String password) {
this.password = password;
}

public int getPort() {
retu this.port;
}

public void setPort(int port) {
this.port = port;
}

public boolean isSsl() {
retu this.ssl;
}

public void setSsl(boolean ssl) {
this.ssl = ssl;
}

public void setTimeout(int timeout) {
this.timeout = timeout;
}

public int getTimeout() {
retu this.timeout;
}

public Sentinel getSentinel() {
retu this.sentinel;
}

public void setSentinel(Sentinel sentinel) {
this.sentinel = sentinel;
}

public Pool getPool() {
retu this.pool;
}

public void setPool(Pool pool) {
this.pool = pool;
}

public Cluster getCluster() {
retu this.cluster;
}

public void setCluster(Cluster cluster) {
this.cluster = cluster;
}

/**
* Pool properties.
*/
public static class Pool {

/**
* Max number of "idle" connections in the pool. Use a negative value to indicate
* an unlimited number of idle connections.
*/
private int maxIdle = 8;

/**
* Target for the minimum number of idle connections to maintain in the pool. This
* setting only has an effect if it is positive.
*/
private int minIdle = 0;

/**
* Max number of connections that can be allocated by the pool at a given time.
* Use a negative value for no limit.
*/
private int maxActive = 8;

/**
* Maximum amount of time (in milliseconds) a connection allocation should block
* before throwing an exception when the pool is exhausted. Use a negative value
* to block indefinitely.
*/
private int maxWait = -1;

public int getMaxIdle() {
retu this.maxIdle;
}

public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}

public int getMinIdle() {
retu this.minIdle;
}

public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}

public int getMaxActive() {
retu this.maxActive;
}

public void setMaxActive(int maxActive) {
this.maxActive = maxActive;
}

public int getMaxWait() {
retu this.maxWait;
}

public void setMaxWait(int maxWait) {
this.maxWait = maxWait;
}

}

/**
* Cluster properties.
*/
public static class Cluster {

/**
* Comma-separated list of "host:port" pairs to bootstrap from. This represents an
* "initial" list of cluster nodes and is required to have at least one entry.
*/
private List<String> nodes;

/**
* Maximum number of redirects to follow when executing commands across the
* cluster.
*/
private Integer maxRedirects;

public List<String> getNodes() {
retu this.nodes;
}

public void setNodes(List<String> nodes) {
this.nodes = nodes;
}

public Integer getMaxRedirects() {
retu this.maxRedirects;
}

public void setMaxRedirects(Integer maxRedirects) {
this.maxRedirects = maxRedirects;
}

}

/**
* Redis sentinel properties.
*/
public static class Sentinel {

/**
* Name of Redis server.
*/
private String master;

/**
* Comma-separated list of host:port pairs.
*/
private String nodes;

public String getMaster() {
retu this.master;
}

public void setMaster(String master) {
this.master = master;
}

public String getNodes() {
retu this.nodes;
}

public void setNodes(String nodes) {
this.nodes = nodes;
}

}

}

四、源码地址

点我查看

作者:Java小白_Mr.Yang
来源链接: http://www.it-online.cn/2019/08/22/SpringBoot%E6%95%B4%E5%90%88Redis/

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。





本文链接:https://www.javaclub.cn/java/10030.html

分享给朋友: