Spring Boot项目中Redisson版本冲突的解决方案

【故障排查实录】Spring Boot项目中Redisson版本冲突的解决方案

关键词:Spring Boot, Redisson, 依赖冲突, NoClassDefFoundError, 多模块项目

1. 问题背景:突如其来的运行时异常

在开发一个基于Spring Boot 2.7.3的多模块企业级项目时,突然遇到了一个令人困惑的运行时异常:

org.springframework.web.util.NestedServletException: Handler dispatch failed; 
nested exception is java.lang.NoClassDefFoundError: 
org/redisson/client/protocol/convertor/EmptyListConvertor

这个异常发生在调用涉及Redis操作的业务接口时,系统提示找不到EmptyListConvertor类,但编译阶段一切正常。

2. 深入排查:定位问题根源

2.1 初步分析

NoClassDefFoundError通常表明:

  • 编译时类存在,但运行时缺失
  • 可能存在依赖冲突或版本不兼容
  • 类路径问题或依赖范围错误

2.2 依赖树分析

使用Maven命令查看具体的依赖关系:

mvn dependency:tree "-Dincludes=org.redisson"

输出结果显示了一个危险的信号:

[INFO] +- org.redisson:redisson-spring-boot-starter:jar:3.25.0:compile
[INFO] |  +- org.redisson:redisson:jar:3.16.8:compile
[INFO] |  \- org.redisson:redisson-spring-data-32:jar:3.25.0:compile
[INFO] +- org.redisson:redisson:jar:3.16.8:compile
[INFO] \- org.redisson:redisson-spring-data-16:jar:3.16.8:compile

发现的问题:

  1. 版本混合:同时存在Redisson 3.16.8和3.25.0
  2. 适配器不匹配:使用了不兼容的redisson-spring-data-32(用于Spring Boot 3.x)
  3. 多重冲突:多个不同版本的适配器并存

2.3 根本原因查明

经过深入研究Redisson的版本变更记录,发现:

Redisson 3.17.0版本的重大变更:

  • 移除了EmptyListConvertor
  • 改变了内部协议转换器的实现方式
  • 需要配合Spring Data Redis 3.x+使用

而我们的项目环境:

  • Spring Boot 2.7.3 → Spring Data Redis 2.7.x
  • 需要Redisson 3.16.x版本保持兼容性

3. 解决方案:系统性的依赖治理

3.1 版本统一策略

首先在父POM中统一管理版本:

<properties>
    <!-- 其他配置保持不变 -->
    <redisson.version>3.16.8</redisson.version>
    <spring-data-redis.version>2.7.3</spring-data-redis.version>
</properties>

<dependencyManagement>
    <dependencies>
        <!-- Redisson 核心依赖 -->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>${redisson.version}</version>
        </dependency>
        
        <!-- 使用兼容的Spring Data适配器 -->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-data-26</artifactId>
            <version>${redisson.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

版本选择说明:

  • redisson-spring-data-26:兼容Spring Data Redis 2.6.x
  • 虽然项目使用Spring Data Redis 2.7.x,但API兼容性良好
  • 3.16.8版本在阿里云Maven仓库中确认可用

3.2 模块依赖清理

sky-common模块(保持核心依赖):

<dependencies>
    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson</artifactId>
    </dependency>
    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson-spring-data-26</artifactId>
    </dependency>
</dependencies>

sky-server模块(移除重复依赖):

<!-- 注释或删除重复的Redisson依赖声明 -->
<!-- 依赖通过sky-common传递即可 -->

3.3 配置属性统一管理

创建配置属性类RedissonProperties

@Data
@Component
@ConfigurationProperties(prefix = "redisson")
public class RedissonProperties {
    private String host;
    private String port;
    private String password;
    private int database;
    private int connectionMinIdleSize;
    private int connectionPoolSize;
}

对应的配置文件:

redisson:
  host: ${sky.redisson.host}
  port: ${sky.redisson.port}
  database: ${sky.redisson.database}
  password: ${sky.redisson.password}
  connection-min-idle-size: ${sky.redisson.connection-min-idle-size}
  connection-pool-size: ${sky.redisson.connection-pool-size}

3.4 Redisson客户端配置

@Bean
public RedissonClient redissonClient(RedissonProperties redissonProperties) {
    Config config = new Config();
    String address = "redis://" + redissonProperties.getHost() + 
                    ":" + redissonProperties.getPort();
    
    config.useSingleServer()
            .setAddress(address)
            .setDatabase(redissonProperties.getDatabase())
            .setConnectionMinimumIdleSize(redissonProperties.getConnectionMinIdleSize())
            .setConnectionPoolSize(redissonProperties.getConnectionPoolSize());
    
    if (StringUtils.hasText(redissonProperties.getPassword())) {
        config.useSingleServer().setPassword(redissonProperties.getPassword());
    }
    
    return Redisson.create(config);
}

4. 验证与测试

4.1 依赖树验证

执行命令确认依赖统一:

mvn dependency:tree "-Dincludes=org.redisson"

期望输出:

[INFO] +- org.redisson:redisson:jar:3.16.8:compile
[INFO] \- org.redisson:redisson-spring-data-26:jar:3.16.8:compile

4.2 功能测试验证

  1. 基本Redis操作测试:set/get/delete操作
  2. Redisson高级功能测试:分布式锁、布隆过滤器
  3. 集成测试:业务接口调用Redis功能

5. 经验总结与最佳实践

5.1 排查流程总结

运行时异常
查看完整堆栈信息
分析依赖树
确认版本兼容性
统一依赖管理
清理本地仓库
验证解决方案
文档记录

5.2 预防措施

  1. 版本兼容性矩阵:建立项目组件版本兼容表
  2. 依赖统一管理:所有依赖版本在父POM中集中管理
  3. 定期依赖检查:使用mvn dependency:tree定期检查
  4. CI/CD集成:在流水线中加入依赖冲突检查步骤

5.3 常用命令备忘

# 检查特定依赖
mvn dependency:tree -Dincludes=groupId:artifactId

# 强制更新依赖
mvn clean install -U

# 清理本地仓库
rm -rf ~/.m2/repository/org/redisson/

# 检查依赖冲突
mvn dependency:analyze-duplicate

6. 结语

这次Redisson版本冲突的排查过程,深刻提醒我们在微服务和多模块项目中依赖管理的重要性。通过系统性的排查思路和方法,不仅解决了眼前的问题,更重要的是建立了一套预防类似问题的机制。

关键收获:

  • 依赖冲突排查需要系统性思维
  • 版本兼容性检查应该成为开发流程的一部分
  • 良好的项目结构设计和依赖管理能避免很多潜在问题

希望这篇详细的排查记录能够帮助遇到类似问题的开发者快速定位和解决问题。

posted @ 2025-09-21 07:38  WILK  阅读(0)  评论(0)    收藏  举报  来源