SpringBoot升级2.6+swagger启动报错-Spring专区论坛-技术-SpringForAll社区

SpringBoot升级2.6+swagger启动报错

背景

原先的项目一部分在使用 SpringBoot 2.4,但 2.4 的版本中对于线程池没有默认的监控,需要自己去实现。但是在 2.6 版本有默认实现监控,所以想将项目升级到 2.6。

升级&问题

SpringBoot 和 SpringCloud 版本的对应关系,参考:https://start.spring.io/actuator/info

修改好 pom 后,刷新 maven 没有报错,启动出现了异常,核心错误如下:

Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException

网上检索到的原因和解决方案,如下:

原因:这是因为 Springfox 使用的路径匹配是基于 AntPathMatcher 的,而 Spring Boot 2.6.X 使用的是 PathPatternMatcher。
解决:

  1. 在 application.properties 里配置:spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER。
  2. 添加如下代码
@Bean
public static 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");
                field.setAccessible(true);
                return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
            } catch (IllegalArgumentException | IllegalAccessException e) {
                throw new IllegalStateException(e);
            }
        }
    };
}

具体可参考:https://github.com/springfox/springfox/issues/3462

适应新版本的解决方案

上述的方案,试过没有什么问题,但是感觉侵入性太强,修改了 spring 升级的内容,仔细看了 issue 的回复

issue信息

spring 官方其实已经推出了新的 springdoc 来作为 springfox 的替代。

按照文档进行迁移:https://springdoc.org/migrating-from-springfox.html ,其实就两步:

  1. 删除 swagger 的 jar 包和相关配置
  2. 引入 jar 包
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.7.0</version>
</dependency>
  1. 增加 springdoc 的配置,如下是我的 demo 案例
@Configuration
public class SpringdocConfiguration {

    @Bean
    public GroupedOpenApi publicApi() {
        String[] contextHeaderNames = new String[]{"M-Token", "M-UserId"};
        return GroupedOpenApi.builder()
                .group("mine-demo")
                .packagesToScan("io.github.demo")
                .pathsToMatch("/**")
                .addOperationCustomizer((operation, handlerMethod) -> {
                    for (String contextHeaderName : contextHeaderNames) {
                        Parameter missingParam = new Parameter()
                                .in(ParameterIn.HEADER.toString())
                                .schema(new StringSchema())
                                .name(contextHeaderName);
                        operation.addParametersItem(missingParam);
                    }
                    return operation;
                })
                .build();
    }

    @Bean
    public OpenAPI apiInfo() {
        return new OpenAPI().info(new Info().title("mine测试案例").version("1.0.0"));
    }
}
  1. 刷新 maven,启动,访问/swagger-ui.html 即可跳转到/swagger-ui/index.html

springdoc效果

使用 knife4j 的 ui

  1. 引入 jar 包,这里注意下版本,具体看官方文档:https://doc.xiaominfo.com/,我这边用的是 spring boot 2.6,所以对应使用
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
    <version>4.1.0</version>
</dependency>

这里需要注意 knife4j 中已经依赖了 springdoc-openapi-ui,如果和前面引入的版本不一致,则需要把前面引入的 jar 移除掉,不然会版本冲突。

  1. 在 application.yml 中增加配置,开启 knife4j 的 ui
knife4j:
  enable: true
  1. 刷新 maven 启动,访问/doc.html

knife效果

请登录后发表评论