Spring Boot 2.6.0 Springfox 启动失败:documentationPluginsBootstrapper 错误解决方案
问题描述
在 Spring Boot 2.6.0 及以上版本中,当使用 Springfox 3.x 时,应用程序启动时可能会遇到以下错误:
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper';
nested exception is java.lang.NullPointerException: Cannot invoke
"org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()"
because "this.condition" is null
这个问题的根本原因是 Spring Boot 2.6.0 引入了默认的路径匹配策略变更,与 Springfox 库存在兼容性问题。
问题根源
自 Spring Boot 2.6.0 开始,默认的路径匹配策略从 AntPathMatcher
改为 PathPatternParser
。Springfox 3.x 版本在设计时假设 Spring MVC 使用的是基于 Ant 的路径匹配器,因此在新版本的 Spring Boot 中会出现兼容性问题。
注意
如果您同时使用了 Spring Boot Actuator,情况会更加复杂。Actuator 始终使用基于 PathPattern 的解析器,不受 matching-strategy
配置的影响。
解决方案
方案一:修改路径匹配策略(适用于无 Actuator 的场景)
在 application.properties
文件中添加以下配置:
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
这个简单的配置可以解决大多数情况下的问题,但如果您使用了 Spring Boot Actuator,可能需要下面的方案。
方案二:自定义 Bean 配置(适用于包含 Actuator 的场景)
添加以下 Bean 配置类:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring web.plugins.WebMvcRequestHandlerProvider;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Configuration
public class SpringFoxConfig {
@Bean
public BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
List<T> copy = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
if (Objects.isNull(field)) {
return new ArrayList<>();
}
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
}
方案三:降级 Spring Boot 版本
如果以上方案对您不适用,可以考虑将 Spring Boot 降级到 2.5.x 版本:
// build.gradle
plugins {
id 'org.springframework.boot' version '2.5.6' // 使用 2.5.x 版本
// 其他配置...
}
方案四:迁移到 Springdoc OpenAPI
考虑到 Springfox 已停止维护,迁移到 Springdoc OpenAPI 是推荐的长期解决方案。
- 添加依赖:
// build.gradle
implementation "org.springdoc:springdoc-openapi-ui:1.6.4"
- 在主应用类上添加注解:
@SpringBootApplication
@OpenAPIDefinition
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
- 访问 Swagger UI:
http://localhost:8080/swagger-ui/index.html
完整配置示例
如果您决定继续使用 Springfox,以下是完整的配置示例:
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket apiDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.apiInfo(metadata());
}
private ApiInfo metadata() {
return new ApiInfoBuilder()
.title("API文档")
.description("API接口文档")
.version("1.0")
.contact(new Contact("开发团队", "", "contact@example.com"))
.build();
}
// 添加方案二中的 BeanPostProcessor
@Bean
public BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
// 实现同上
}
}
# application.properties
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
总结
Spring Boot 2.6.0 与 Springfox 3.x 的兼容性问题主要由路径匹配策略变更引起。您可以根据自己的项目需求选择适合的解决方案:
- 简单应用:使用
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
- 包含 Actuator 的应用:添加自定义 BeanPostProcessor 配置
- 长期项目:考虑迁移到 Springdoc OpenAPI
- 临时解决:降级 Spring Boot 到 2.5.x 版本
建议
对于新项目,强烈推荐使用 Springdoc OpenAPI 替代 Springfox,因为它提供了更好的兼容性和持续的维护支持。
通过以上解决方案,您应该能够解决 Spring Boot 2.6.0 与 Springfox 3.x 的兼容性问题,并成功启动应用程序。