依赖版本冲突:
spingboot 3.5.3
knife4j 4.5.0
使用注解 @ControllerAdvice 时访问接口文档出现报错
jakarta.servlet.ServletException: Handler dispatch failed: java.lang.NoSuchMethodError: 'void org.springframework.web.method.ControllerAdviceBean.<init>(java.lang.Object)'
核心问题:Spring Boot版本兼容性
解决方法
1. 使用 4j 的 @Hidden 将全局异常类忽略(选用)
2. 将 springboot 版本降级 由3.5.3降到 3.2.5
问题关键点解析总结
1. 核心问题:Spring Boot版本兼容性
-
根本原因:Spring Boot 3.5.3 中
ControllerAdviceBean
类的构造方法签名发生变更(从单参数Object
改为多参数),但 Knife4j 的依赖库未同步适配此变更。 -
错误触发点:
-
Knife4j 内部代码尝试调用
ControllerAdviceBean
的旧构造方法:new ControllerAdviceBean(Object bean)
。 -
Spring Boot 3.5.3 中已移除该构造方法,导致
NoSuchMethodError
。
-
2. 技术细节分析
-
Spring Framework 内部变更:
-
Spring Boot 3.2.5 对应 Spring Framework 6.0.x,保留旧构造方法。
-
Spring Boot 3.5.3 对应 Spring Framework 6.1.x,
ControllerAdviceBean
重构为:java
// 新版本构造方法(需额外参数) public ControllerAdviceBean(Object bean, BeanFactory beanFactory) { ... }
-
-
Knife4j 的兼容性问题:
-
Knife4j 依赖的底层库(如
springfox
或springdoc-openapi
)未及时适配 Spring Framework 6.1.x 的破坏性变更。
-
3. 解决方案对比
方案 | 原理 | 优缺点 |
---|---|---|
@Hidden 注解忽略异常类 | 阻止 Knife4j 扫描全局异常类,避免触发不兼容代码 | ✅ 快速修复 ❌ 可能隐藏其他需展示的异常信息 |
降级 Spring Boot 版本 | 回退到兼容旧构造方法的版本(3.2.5) | ✅ 彻底解决问题 ❌ 放弃新版本特性/安全更新 |
升级 Knife4j 依赖 | 等待 Knife4j 发布适配 Spring Boot 3.5.3 的版本(最优解) | ✅ 长期兼容 ❌ 可能需等待官方更新 |
4. 问题本质总结
-
三方库协作问题:Knife4j 对 Spring Framework 内部类的强依赖导致版本升级时兼容性断裂。
-
语义化版本约束:Spring Boot 3.2.x → 3.5.x 属次版本号升级(
3.X
),但包含不兼容的底层 API 变更(违反语义化版本规范)。 -
临时规避合理性:
-
@Hidden
是 Swagger 原生注解,对 Knife4j 安全有效。 -
降级版本是验证兼容性的直接手段,但非长远之计。
-
推荐长期解决方案
-
检查 Knife4j 更新:
<!-- 尝试升级到最新 Knife4j 版本 --> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <version>4.5.0</version> <!-- 确认支持 Spring Boot 3.5.x --> </dependency>
-
替换为 SpringDoc OpenAPI(官方推荐):
<!-- 使用标准 SpringDoc 替代 Knife4j --> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.5.0</version> </dependency>
-
自定义适配层(高级方案):
// 重写 Knife4j 相关组件,适配新版 ControllerAdviceBean @Bean public CustomKnife4jAdapter knife4jAdapter() { return new CustomKnife4jAdapter(); // 避免调用旧构造方法 }
结论:问题根源是 Knife4j 与 Spring Boot 3.5.3 的兼容性断裂。短期可用
@Hidden
或降级修复,长期需推动 Knife4j 升级或切换至 SpringDoc。建议优先升级 Knife4j 或迁移到 SpringDoc 以保持框架最新。