解决java.lang.NoClassDefFoundError: org/springframework/data/redis/connection/RedisStreamCommands
这是在 springboot 中使用 redisson 时,因为引入的依赖为
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.14.0</version>
</dependency>
这个依赖,通过阅读源码,可以知道其中排除了默认的 jedis 以及 lettuce。参考
package org.redisson.spring.starter; 包下的
RedissonAutoConfiguration 类
由于redisson-starter 的支持随着 springboot 版本的调整也有所升级,因此最新版本的 starter 基本都是 springboot2.3的依赖。所以当我们使用 springboot2.3 以下的版本时,就会出现 classnotfound
解决方法:
排除springboot2.3 支持,引入 springboot2.1 支持。
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.14.0</version>
<exclusions>
<exclusion>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-23</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-21</artifactId>
<version>3.14.0</version>
</dependency>
具体 springboot 支持参考官方文档
引申:
最新 redisson-starter 因为解决了 application.yml配置文件中直接配置 redisson 的问题,也就是说我们不用再编辑一个 redisson.yml的文件来配置 redisson,这解决了使用配置中心管理配置的尴尬。
spring:
redis:
database: 0
password: password
cluster:
nodes: 127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7002
# Redisson settings
redisson:
# file: classpath:redisson.yaml
config: |
clusterServersConfig:
idleConnectionTimeout: 10000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
failedSlaveReconnectionInterval: 3000
failedSlaveCheckInterval: 60000
password: Index1130
subscriptionsPerConnection: 5
clientName: redisson
loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}
subscriptionConnectionMinimumIdleSize: 1
subscriptionConnectionPoolSize: 50
slaveConnectionMinimumIdleSize: 50
slaveConnectionPoolSize: 200
masterConnectionMinimumIdleSize: 50
masterConnectionPoolSize: 100
readMode: "SLAVE"
subscriptionMode: "SLAVE"
nodeAddresses:
- "redis://127.0.0.1:7002"
- "redis://127.0.0.1:7001"
- "redis://127.0.0.1:7000"
scanInterval: 1000
pingConnectionInterval: 0
keepAlive: false
tcpNoDelay: false
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.MarshallingCodec> {}
transportMode: "NIO"
lockWatchdogTimeout: 30000
源码:
@Bean(
destroyMethod = "shutdown"
)
@ConditionalOnMissingBean({RedissonClient.class})
public RedissonClient redisson() throws IOException {
Config config = null;
Method clusterMethod = ReflectionUtils.findMethod(RedisProperties.class, "getCluster");
Method timeoutMethod = ReflectionUtils.findMethod(RedisProperties.class, "getTimeout");
Object timeoutValue = ReflectionUtils.invokeMethod(timeoutMethod, this.redisProperties);
int timeout;
Method nodesMethod;
if (null == timeoutValue) {
timeout = 10000;
} else if (!(timeoutValue instanceof Integer)) {
nodesMethod = ReflectionUtils.findMethod(timeoutValue.getClass(), "toMillis");
timeout = ((Long)ReflectionUtils.invokeMethod(nodesMethod, timeoutValue)).intValue();
} else {
timeout = (Integer)timeoutValue;
}
if (this.redissonProperties.getConfig() != null) {
try {
config = Config.fromYAML(this.redissonProperties.getConfig());
} catch (IOException var13) {
try {
config = Config.fromJSON(this.redissonProperties.getConfig());
} catch (IOException var12) {
throw new IllegalArgumentException("Can't parse config", var12);
}
}
} else if (this.redissonProperties.getFile() != null) {
try {
InputStream is = this.getConfigStream();
config = Config.fromYAML(is);
} catch (IOException var11) {
try {
InputStream is = this.getConfigStream();
config = Config.fromJSON(is);
} catch (IOException var10) {
throw new IllegalArgumentException("Can't parse config", var10);
}
}
} else if (this.redisProperties.getSentinel() != null) {
nodesMethod = ReflectionUtils.findMethod(Sentinel.class, "getNodes");
Object nodesValue = ReflectionUtils.invokeMethod(nodesMethod, this.redisProperties.getSentinel());
String[] nodes;
if (nodesValue instanceof String) {
nodes = this.convert(Arrays.asList(((String)nodesValue).split(",")));
} else {
nodes = this.convert((List)nodesValue);
}
config = new Config();
((SentinelServersConfig)config.useSentinelServers().setMasterName(this.redisProperties.getSentinel().getMaster()).addSentinelAddress(nodes).setDatabase(this.redisProperties.getDatabase()).setConnectTimeout(timeout)).setPassword(this.redisProperties.getPassword());
} else {
Method method;
if (clusterMethod != null && ReflectionUtils.invokeMethod(clusterMethod, this.redisProperties) != null) {
Object clusterObject = ReflectionUtils.invokeMethod(clusterMethod, this.redisProperties);
method = ReflectionUtils.findMethod(clusterObject.getClass(), "getNodes");
List<String> nodesObject = (List)ReflectionUtils.invokeMethod(method, clusterObject);
String[] nodes = this.convert(nodesObject);
config = new Config();
((ClusterServersConfig)config.useClusterServers().addNodeAddress(nodes).setConnectTimeout(timeout)).setPassword(this.redisProperties.getPassword());
} else {
config = new Config();
String prefix = "redis://";
method = ReflectionUtils.findMethod(RedisProperties.class, "isSsl");
if (method != null && (Boolean)ReflectionUtils.invokeMethod(method, this.redisProperties)) {
prefix = "rediss://";
}
((SingleServerConfig)config.useSingleServer().setAddress(prefix + this.redisProperties.getHost() + ":" + this.redisProperties.getPort()).setConnectTimeout(timeout)).setDatabase(this.redisProperties.getDatabase()).setPassword(this.redisProperties.getPassword());
}
}
if (this.redissonAutoConfigurationCustomizers != null) {
Iterator var19 = this.redissonAutoConfigurationCustomizers.iterator();
while(var19.hasNext()) {
RedissonAutoConfigurationCustomizer customizer = (RedissonAutoConfigurationCustomizer)var19.next();
customizer.customize(config);
}
}
return Redisson.create(config);
}
# 当我们配置了spring.redis.redisson.config这个属性时,会优先以此属性为 redisson 配置
if (this.redissonProperties.getConfig() != null) {
try {
config = Config.fromYAML(this.redissonProperties.getConfig());
} catch (IOException var13) {
try {
config = Config.fromJSON(this.redissonProperties.getConfig());
} catch (IOException var12) {
throw new IllegalArgumentException("Can't parse config", var12);
}
}
}
官方链接 配置
redisson 各种配置项以及集群 哨兵 单机配置,参考 redisson 官方文档 集群配置
由于目前网上,此类解决办法,全是千篇一律的直接降级 redisson-starter 的文章,希望各位朋友使用一个东西遇到问题的时候,首先看官方的 github,其次自己尝试阅读源码。当你选择降级的时候,你可能选择的是舍弃了最新的某些功能以及支持。
本文地址:https://blog.csdn.net/Model_Vincent/article/details/112004508
上一篇: 支付宝怎么免费定制春联?支付宝领取免费定制春联教程
下一篇: 线程初学