spring-boot-start-actuator版本2.6.x与swagger冲突问题

卢权
2023-12-01

pring-boot-starter-actuator是spring提供的监控模块。在运行中,需实时和定时监控服务各项状态和可用性。提供很多监控接口,可对应用系统进行配置查看、相关统计等。
Swagger 是一个规范和完整的框架,生成、描述、调用和可视化 RESTful 风格的 Web 服务。是OpenAPI规范Java实现。
问题是,项目开始只引用了 swagger 启动没问题,在最近需要监控项目的时候,引入了actuator和prometheus,启动报错:Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException

参考

使用本链接内容解决:SpringBoot2.6,在有spring-boot-starter-actuator依赖的情况下报错,2.5.7正常启动
spring-boot-start-actuator版本2.6.x之后导致swagger冲突问题

SpringBoot2.6.x集成swagger: Failed to start bean ‘documentationPluginsBootstrapper问题解决
SpringBoot教程(十六) | SpringBoot集成swagger(全网最全)
springboot整合swagger2依赖冲突问题解决思路
knife4j和springboot-actuator版本冲突问题
knife4j介绍

记录

pom

大概内容如下

<parent>
    <artifactId>spring-boot-starter-parent</artifactId>
    <groupId>org.springframework.boot</groupId>
    <version>2.6.3</version>
    <relativePath/>
</parent>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <swagger2.version>2.9.2</swagger2.version>
    ...
</properties>
<dependencies>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-bootstrap</artifactId>
     </dependency>
     ...
	<dependency>
	    <groupId>io.springfox</groupId>
	    <artifactId>springfox-swagger2</artifactId>
	    <version>${swagger2.version}</version>
	</dependency>
	<dependency>
	    <groupId>io.springfox</groupId>
	    <artifactId>springfox-swagger-ui</artifactId>
	    <version>${swagger2.version}</version>
	</dependency>
	...
    <!--    以上内容启动没问题,增加下面内容启动失败    -->
    <!--    增加springboot的指标检测    -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <!--    增加springboot的prometheus监控指标检测    -->
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-registry-prometheus</artifactId>
    </dependency>
<dependencies>

报错日志

org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181)
	at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54)
	at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356)
	at java.lang.Iterable.forEach(Iterable.java:75)
	at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155)
	at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123)
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:414)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292)
	at org.xxx.xxx.XXXApplication.main(XXXApplication.java:36)
Caused by: java.lang.NullPointerException: null
	at springfox.documentation.spi.service.contexts.Orderings$8.compare(Orderings.java:112)
	at springfox.documentation.spi.service.contexts.Orderings$8.compare(Orderings.java:109)
	at com.google.common.collect.ComparatorOrdering.compare(ComparatorOrdering.java:37)
	at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
	at java.util.TimSort.sort(TimSort.java:234)
	at java.util.Arrays.sort(Arrays.java:1438)
	at com.google.common.collect.Ordering.sortedCopy(Ordering.java:852)
	at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:57)
	at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper$2.apply(DocumentationPluginsBootstrapper.java:138)
	at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper$2.apply(DocumentationPluginsBootstrapper.java:135)
	at com.google.common.collect.Iterators$6.transform(Iterators.java:788)
	at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47)
	at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47)
	at com.google.common.collect.Iterators$ConcatenatedIterator.hasNext(Iterators.java:1340)
	at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:270)
	at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:234)
	at com.google.common.collect.FluentIterable.toList(FluentIterable.java:617)
	at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.defaultContextBuilder(DocumentationPluginsBootstrapper.java:111)
	at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.buildContext(DocumentationPluginsBootstrapper.java:96)
	at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:167)
	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178)
	... 14 common frames omitted

解决思路

明显是版本冲突导致的,随便搜一下就可以找到问题的大致说明:

因Springfox 使用的路径匹配是基于AntPathMatcher的,而Spring Boot 2.6.X使用的是PathPatternMatcher。

解决方式1-降低springboot版本-未采用

考虑到项目已上线,故不太建议轻易变动框架版本

解决方式2-actuator增加解决代码

增加配置

spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

增加处理代码


import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 解决依赖代码冲突问题
 *
 * @author z.y.
 * @version v1.0
 * @date 2022
 */
@Configuration
public class ConflictHandlingCfg {
    /**
     * 解决springboot升到2.6.x之后,knife4j报错
     * 原文链接:https://gitee.com/xiaoym/knife4j/issues/I4JT89
     * @param wes        the web endpoints supplier
     * @param ses    the servlet endpoints supplier
     * @param ces the controller endpoints supplier
     * @param emt          the endpoint media types
     * @param cep      the cors properties
     * @param wep       the web endpoints properties
     * @param env                 the environment
     * @return the web mvc endpoint handler mapping
     */
    @Bean
    public WebMvcEndpointHandlerMapping webMvcEndpointHandlerMapping(WebEndpointsSupplier wes
            , ServletEndpointsSupplier ses, ControllerEndpointsSupplier ces, EndpointMediaTypes emt
            , CorsEndpointProperties cep, WebEndpointProperties wep,Environment env) {
        List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
        Collection<ExposableWebEndpoint> webEndpoints = wes.getEndpoints();
        allEndpoints.addAll(webEndpoints);
        allEndpoints.addAll(ses.getEndpoints());
        allEndpoints.addAll(ces.getEndpoints());
        String basePath = wep.getBasePath();
        EndpointMapping endpointMapping = new EndpointMapping(basePath);
        boolean shouldRegisterLinksMapping = shouldRegisterLinksMapping(wep, env, basePath);
        return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, emt
                , cep.toCorsConfiguration(), new EndpointLinksResolver(
                allEndpoints, basePath), shouldRegisterLinksMapping, null);
    }
    /**
     * shouldRegisterLinksMapping
     *
     * @param wep
     * @param env
     * @param basePath
     * @return
     */
    private boolean shouldRegisterLinksMapping(WebEndpointProperties wep, Environment env, String basePath) {
        return wep.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(env).equals(ManagementPortType.DIFFERENT));
    }
}

问题解决。记录一下

END

 类似资料: