spring-boot-start-actuator版本2.6.x之后导致swagger冲突问题

袁运锋
2023-12-01

1、问题描述

  新起了一个项目,起引入依赖大致如下:

...
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>2.0.7</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    <version>2.7.3</version>
</dependency>
...

  配置大致如下:

server:
  port: 9091
management:
  endpoint:
    shutdown:
      enabled: true # 开启端点
    health:
      show-details: always # 是否展示健康检查详情
  endpoints:
    web:
      exposure:
        include: '*' # 暴露所有端点
...

  但是在项目启动是报错如下:

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)
...	

2、问题分析

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

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

3、问题解决

3.1、解决方案一:降低版本号

  找到问题就好解决了,很明显的一种解决方案是降版本。稳定版本匹配如下:

springboot版本swagger版本
2.5.62.9.2

3.2、解决方案二:不降低版本

  很多时候我们是不能轻易的降低项目中依赖版本号的,而这里网上很多解决方案都是添加以下的配置:

spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

  该配置在部分版本中可能会解决问题,但是在我的项目中,依旧报同样的错误,此时参考github上一个大佬的解决方案,再添加一个bean就能解决以上的问题了。在之前配置的swaggerConfig中添加以下代码:

/**
 * 解决springboot升到2.6.x之后,knife4j报错
 *
 * @param webEndpointsSupplier        the web endpoints supplier
 * @param servletEndpointsSupplier    the servlet endpoints supplier
 * @param controllerEndpointsSupplier the controller endpoints supplier
 * @param endpointMediaTypes          the endpoint media types
 * @param corsEndpointProperties      the cors properties
 * @param webEndpointProperties       the web endpoints properties
 * @param environment                 the environment
 * @return the web mvc endpoint handler mapping
 */
@Bean
public WebMvcEndpointHandlerMapping webMvcEndpointHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier,
                                                                 ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes,                                                                     CorsEndpointProperties corsEndpointProperties, WebEndpointProperties webEndpointProperties,
                                                                 Environment environment) {
    List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
    Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
    allEndpoints.addAll(webEndpoints);
    allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
    allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
    String basePath = webEndpointProperties.getBasePath();
    EndpointMapping endpointMapping = new EndpointMapping(basePath);
    boolean shouldRegisterLinksMapping = shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
    return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsEndpointProperties.toCorsConfiguration(), new EndpointLinksResolver(
                allEndpoints, basePath), shouldRegisterLinksMapping, null);
}

/**
 * shouldRegisterLinksMapping
 *
 * @param webEndpointProperties
 * @param environment
 * @param basePath
 * @return
 */
private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) {
    return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
}

  搞定,问题解决!

4、参考资料

  1. https://zhuanlan.zhihu.com/p/474764240
  2. https://gitee.com/xiaoym/knife4j/issues/I4JT89
  3. https://github.com/springfox/springfox/issues/3462
 类似资料: