首页 归档 关于 文件 Github
×

SpringBoot之自定义Redis配置

2020-11-17 17:45:41
Redis
  • SpringBoot
本文总阅读量(次):
本文字数统计(字):1.3k
本文阅读时长(分):7

修改原生的yml配置,采取自定义模式,

依赖

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

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<skipTests>true</skipTests>
<spring-boot.version>2.4.2</spring-boot.version>
</properties>

<dependencies>
<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>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>

配置

创建Bean的注入方式,使用 @ConditionalOnMissingClass 注解 进行判断bean是否存在,
如不存在则加载当前默认bean,如存在则使用配置bean.

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
@Data
@Component(value = "redisDataConfig")
@ConditionalOnMissingClass(value = "redisDataConfig")
public class RedisDataConfig {

// 服务器地址
private List<String> hostname = Collections.singletonList("127.0.0.1:6379");
// 数据库索引(默认为0)
private Integer database = 0;
// 服务器连接密码(默认为空)
private String password;

/* 哨兵 */
// 哨兵监听的 master名称(mymaster)
private String master;

/* 集群 */
private Integer maxRedirects = 3;
private Integer refreshTime = 60;

/* 其他 */
// 服务器连接名称(默认为空)
private String username;
// 连接超时时间(毫秒)默认是2000ms
private Long timeout = 10000L;
// 连接池最大连接数(使用负值表示没有限制)
private Integer maxTotal = 200;
// 连接池中的最大空闲连接
private Integer maxIdle = 20;
// 连接池中的最小空闲连接
private Integer minIdle = 0;
// 连接池最大阻塞等待时间(使用负值表示没有限制)
private Long maxWaitMillis = 10000L;

// 调用validated方法进行校验,若校验失败,连接会从连接池中移除并销毁,同时会尝试重新借一个新的连接对象。
private Boolean testOnBorrow = true;
// 归还连接时,会进行检查,检查不通过,销毁。
private Boolean testOnReturn = true;
// 检测本次获取redis链接是否可用,若不可用,则取到可用链接为止
private Boolean testWhileIdle = true;

}

代码

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

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import io.lettuce.core.ReadFrom;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.*;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.Collections;
import java.util.List;

/**
* @className: RedisConfig.java
* @description: Redis配置
* @author: Demon
*/
@Slf4j
@Component
@EnableCaching
public class RedisConfig {

@Resource(name = "redisDataConfig")
private RedisDataConfig redisDataConfig;

@Bean
public RedisConnectionFactory lettuceConnectionFactory() {

GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
genericObjectPoolConfig.setMaxTotal(redisDataConfig.getMaxTotal());
genericObjectPoolConfig.setMaxWaitMillis(redisDataConfig.getMaxWaitMillis());
genericObjectPoolConfig.setMaxIdle(redisDataConfig.getMaxIdle());
genericObjectPoolConfig.setMinIdle(redisDataConfig.getMinIdle());
genericObjectPoolConfig.setTestOnBorrow(redisDataConfig.getTestOnBorrow());
genericObjectPoolConfig.setTestOnReturn(redisDataConfig.getTestOnReturn());
genericObjectPoolConfig.setTestWhileIdle(redisDataConfig.getTestWhileIdle());

LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder lettucePoolingClientConfigurationBuilder = LettucePoolingClientConfiguration.builder()
.poolConfig(genericObjectPoolConfig).commandTimeout(Duration.ofMillis(redisDataConfig.getTimeout())).shutdownTimeout(Duration.ZERO);

List<String> hostname = redisDataConfig.getHostname();
if (hostname.size() > 1) {
String master = redisDataConfig.getMaster();
if (master != null && master.length() > 0) {
// 哨兵模式
log.info("Redis模式:哨兵({})", Collections.singletonList(hostname).toArray());
RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration();
redisSentinelConfiguration.setMaster(master);
redisSentinelConfiguration.setDatabase(redisDataConfig.getDatabase());
redisSentinelConfiguration.setUsername(redisDataConfig.getUsername());
if (redisDataConfig.getPassword() != null && !"".equals(redisDataConfig.getPassword())) {
redisSentinelConfiguration.setPassword(RedisPassword.of(redisDataConfig.getPassword()));
}
for (String sentinelNode : hostname) {
String[] split = sentinelNode.split(":");
redisSentinelConfiguration.addSentinel(new RedisNode(split[0], Integer.parseInt(split[1])));
}
return new LettuceConnectionFactory(redisSentinelConfiguration, lettucePoolingClientConfigurationBuilder.build());
} else {
// 集群模式
log.info("Redis模式:集群({})", Collections.singletonList(hostname).toArray());
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
redisClusterConfiguration.setUsername(redisDataConfig.getUsername());
redisClusterConfiguration.setMaxRedirects(redisDataConfig.getMaxRedirects());
if (redisDataConfig.getPassword() != null && !"".equals(redisDataConfig.getPassword())) {
redisClusterConfiguration.setPassword(RedisPassword.of(redisDataConfig.getPassword()));
}
for (String clusterNode : hostname) {
String[] split = clusterNode.split(":");
redisClusterConfiguration.addClusterNode(new RedisNode(split[0], Integer.parseInt(split[1])));
}
//支持自适应集群拓扑刷新和静态刷新源
ClusterTopologyRefreshOptions clusterTopologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
.enablePeriodicRefresh().enableAllAdaptiveRefreshTriggers().refreshPeriod(Duration.ofSeconds(redisDataConfig.getRefreshTime()))
.build();
ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder().topologyRefreshOptions(clusterTopologyRefreshOptions).build();
//从优先,读写分离,读从可能存在不一致,最终一致性CP
lettucePoolingClientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED).clientOptions(clusterClientOptions).build();
LettucePoolingClientConfiguration clientConfig = lettucePoolingClientConfigurationBuilder.build();
return new LettuceConnectionFactory(redisClusterConfiguration, clientConfig);
}
} else {
// 单机模式
String redisStandaloneHostname = hostname.get(0);
log.info("Redis模式:单机({})", Collections.singletonList(redisStandaloneHostname).toArray());
String[] split = redisStandaloneHostname.split(":");
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(split[0], Integer.parseInt(split[1]));
redisStandaloneConfiguration.setDatabase(redisDataConfig.getDatabase());
if (redisDataConfig.getPassword() != null && !"".equals(redisDataConfig.getPassword())) {
redisStandaloneConfiguration.setPassword(RedisPassword.of(redisDataConfig.getPassword()));
}
redisStandaloneConfiguration.setUsername(redisDataConfig.getUsername());
return new LettuceConnectionFactory(redisStandaloneConfiguration, lettucePoolingClientConfigurationBuilder.build());
}
}

/**
* 配置自定义redisTemplate
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
System.out.println("★★★★★加载 bean - RedisTemplate<String, Object> ★★★★★");
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值 替换默认序列化
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
//使用StringRedisSerializer来序列化和反序列化redis的key值
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
//事务支持
redisTemplate.setEnableTransactionSupport(true);
return redisTemplate;
}

/**
* 缓存配置管理器
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
System.out.println("★★★★★加载 bean - cacheManager ★★★★★");
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
//以锁写入的方式创建RedisCacheWriter对象
RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(redisConnectionFactory);
//创建缓存配置对象
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(redisCacheConfiguration).cacheWriter(writer).build();
}

}

使用

1
2
3
4
5
6
@Resource
private RedisTemplate<String,Object> redisTemplate;


ValueOperations<String,Object> valueOperations = redisTemplate.opsForValue();
valueOperations.set("admin","");
完
Zip4j - 压缩/解压(可设置密码)
MyBatis遍历map

本文标题:SpringBoot之自定义Redis配置

文章作者:十二

发布时间:2020-11-17 17:45:41

最后更新:2022-03-24 16:36:30

原始链接:https://www.zhuqiaolun.com/2020/11/1605606341401/1605606341401/

许可协议:署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

头像

十二

我想起那天夕阳下的奔跑,那是我逝去的青春。

分类

  • Blog4
  • ElasticSearch13
  • Freemarker2
  • Git2
  • Go-FastDfs2
  • IDEA2
  • J-Package6
  • J-Tools21
  • Java2
  • JavaFx3
  • Kafka4
  • Linux2
  • Logger5
  • Maven5
  • MyBatis6
  • MyCat3
  • MySql2
  • Nginx5
  • OceanBase1
  • RabbitMq4
  • Redis6
  • SVN1
  • SpringBoot11
  • Tomcat6
  • WebService2
  • Windows2
  • kubernetes10

归档

  • 二月 20251
  • 十二月 20244
  • 八月 202416
  • 六月 20241
  • 九月 20231
  • 八月 20231
  • 七月 20232
  • 八月 20222
  • 三月 202214
  • 二月 20224
  • 十一月 20211
  • 七月 20215
  • 六月 20213
  • 五月 20213
  • 四月 20211
  • 三月 202116
  • 二月 20212
  • 一月 20211
  • 十一月 202014
  • 十月 20201
  • 九月 202014
  • 八月 20205
  • 七月 20204
  • 六月 20208
  • 五月 20208

作品

我的微信 我的文件

网站信息

本站运行时间统计: 载入中...
本站文章字数统计:96.9k
本站文章数量统计:132
© 2025 十二  |  鄂ICP备18019781号-1  |  鄂公网安备42118202000044号
驱动于 Hexo  | 主题 antiquity  |  不蒜子告之 阁下是第个访客
首页 归档 关于 文件 Github