欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

解决java.lang.NoClassDefFoundError: org/springframework/data/redis/connection/RedisStreamCommands

程序员文章站 2022-06-19 14:58:11
这是在 springboot 中使用 redisson 时,因为引入的依赖为 org.redisson redisson-spring-boot-starter 3.14.0...

这是在 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 支持参考官方文档

解决java.lang.NoClassDefFoundError: org/springframework/data/redis/connection/RedisStreamCommands

引申:

最新 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