knife4j 4.5.0 与 SpringBoot3.4.0-4 不兼容

1
2
3
4
5
6
7
 #复现下场景:

<dependency>
<groupId>com.github.xiaoymin</groupId> com.github.xiaoymin
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> knife4j-openapi3-jakarta-spring-boot-starter
<version>4.5.0</version> 4.5.0 4.5.0 4.5.0
</dependency>

本来想从 SpringBoot 3.3.5 升级到最新的 3.4.4。但是升级后发现 Knife4j 文档地址doc.html进入后报错。

java.lang.NoSuchMethodError: ‘void org.springframework.web.method.ControllerAdviceBean.(java.lang.Object)’

在全局异常解析中可以看到

1
2
3
4
5
6
7
at org.springdoc.core.service.GenericResponseService.lambda$getGenericMapResponse$8(GenericResponseService.java:702) ~[springdoc-openapi-starter-common-2.3.0.jar:2.3.0]
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) ~[na:na]
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) ~[na:na]at org.springdoc.core.service.GenericResponseService.lambda$getGenericMapResponse$8(GenericResponseService.java:702) ~[springdoc-openapi-starter-common-2.3.0.jar:2.3.0]at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) ~[na:na]at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992) ~[na:na]at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) ~[na:na]

GenericResponseService 在 ‘springdoc-openapi-starter-common-2.3.0.jar’ 中
这里可以看到是 org.springdoc.core.service.GenericResponseService中的 getGenericMapResponse 方法。然后在这里找到何处调用了 ControllerAdviceBean 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Map<String, ApiResponse> genericApiResponseMap = (Map) controllerAdviceInfosInThisBean.stream().map(ControllerAdviceInfo::getApiResponseMap).collect(LinkedHashMap::new, Map::putAll, Map::putAll);
for (ControllerAdviceInfo controllerAdviceInfo : this.controllerAdviceInfos.stream().
filter((controllerAdviceInfo) -> (new
ControllerAdviceBean(controllerAdviceInfo.getControllerAdvice())).
isApplicableToBeanType(beanType)).
filter((controllerAdviceInfo) -> !beanType.equals(controllerAdviceInfo.getControllerAdvice().
getClass())).
toList()) {
controllerAdviceInfo.getApiResponseMap().forEach((key, apiResponse) -> {
if (!genericApiResponseMap.containsKey(key)) {
genericApiResponseMap.put(key, apiResponse);
}
});
}

这里可以看到调用的 是一个参数

但是在 SpringBoot 3.4.0 ~4 中 spring-web-6.1.14.jar 的代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
public ControllerAdviceBean(String beanName, BeanFactory beanFactory, ControllerAdvice controllerAdvice) {public ControllerAdviceBean(String beanName, BeanFactory beanFactory, ControllerAdvice controllerAdvice) {
Assert.hasText(beanName, "Bean name must contain text");Assert.hasText(beanName,"Bean name must contain text");
Assert.notNull(beanFactory, "BeanFactory must not be null");Assert.notNull(beanFactory,"BeanFactory must not be null");
Assert.isTrue(beanFactory.containsBean(beanName), () -> "BeanFactory [" + beanFactory +
"] does not contain specified controller advice bean'" + beanName + "'");"] does not contain specified controller advice bean'" + beanName + "'");"] does not contain specified controller advice bean'" + beanName + "'");
Assert.notNull(controllerAdvice, "ControllerAdvice must not be null");Assert.notNull(controllerAdvice, "ControllerAdvice must not be null");

this.beanName = beanName; this.beanName = beanName;
this.isSingleton = beanFactory.isSingleton(beanName); this.isSingleton = beanFactory.isSingleton(beanName);
this.beanType = getBeanType(beanName, beanFactory); this.beanType = getBeanType(beanName, beanFactory);
this.beanTypePredicate = createBeanTypePredicate(controllerAdvice); this.beanTypePredicate = createBeanTypePredicate(controllerAdvice);
this.beanFactory = beanFactory; this.beanFactory = beanFactory;
}

属实是 knif4j 没有跟上节奏


knife4j 4.5.0 与 SpringBoot3.4.0-4 不兼容
http://example.com/2025/02/28/knife4j-4-5-0-与-SpringBoot3-4-0-4-不兼容/
作者
YI MING HUANG
发布于
2025年2月28日
许可协议