写点什么

SpringBoot 升级所踩过的坑 (一)

作者:技术小生
  • 2023-06-05
    北京
  • 本文字数:2948 字

    阅读完需:约 10 分钟

SpringBoot升级所踩过的坑(一)

背景简介

因公司技术更迭,需要将项目统一升级到 SpringBoot2.7.8 版本。而项目中底层依赖的大版本升级,为日常的琐碎工作带来了技术挑战。写下系列文章,将自己在升级过程中遇到的问题以及解决方案,都一一记录下来,避免后人再度陷入泥潭。


问题描述

一般项目中,记录 api 最为方便的就是集成 swagger。而 swagger 在 springboot 升级中出现了严重的问题。升级后,应用居然无法启动。报错信息如下:Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException。


解决方案

出现这个问题,一般就是 springboot 版本和 swagger 版本不兼容导致。那到底 swagger 怎么才能兼容呢。高版本的 springboot 对 swagger2 的兼容性不太好,所以需要将 swagger 升级到 3.0。但是 3.0 相较于 2.X 的版本有比较大的变化。所以升级过程中改动点比较多,我将相关改动点列举如下,希望大家能够借鉴。

  • 引入 swagger3.0 的依赖包,就只有这两个依赖包。

        <dependency>            <groupId>io.springfox</groupId>            <artifactId>springfox-boot-starter</artifactId>            <version>3.0.0</version>        </dependency>
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>3.0.0</version> </dependency>
复制代码
  • 移除项目中所有对于 swagger2.X 的依赖,可以通过 mvn dependency:tree 查看 jar 包的依赖关系,通过在依赖包中添加 exclusions 标签

            <exclusions>                <exclusion>                    <groupId>io.springfox</groupId>                    <artifactId>springfox-swagger2</artifactId>                </exclusion>            </exclusions>
复制代码
  • 删除 swagger2.X 的配置类,增加 swagger3 的配置类,代码如下:

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 org.springframework.web.bind.annotation.RestController;import springfox.documentation.builders.ApiInfoBuilder;import springfox.documentation.builders.PathSelectors;import springfox.documentation.builders.RequestHandlerSelectors;import springfox.documentation.oas.annotations.EnableOpenApi;import springfox.documentation.service.ApiInfo;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;import java.util.Collection;import java.util.List;
@EnableOpenApi@Configurationpublic class SpringSwaggerConfig { /** * 配置基本信息 * @return */ @Bean public ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Swagger Test App Restful API") .description("swagger test app restful api") .termsOfServiceUrl("https://www.hetao.com") .version("1.0") .build(); }
/** * 配置文档生成最佳实践 * @param apiInfo * @return */ @Bean public Docket createRestApi(ApiInfo apiInfo) { return new Docket(DocumentationType.OAS_30) .apiInfo(apiInfo) .groupName("SwaggerGroupOneAPI") .select() .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class)) .paths(PathSelectors.any()) .build(); }
/** * 增加如下配置可解决Spring Boot 6.x 与Swagger 3.0.0 不兼容问题 **/ @Bean public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, 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 = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath); return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null); } private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) { return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT)); }}
复制代码

EnableSwagger2 注解变成了 EnableOpenApi,还增加了一些兼容性的代码。

  • 到这里,还没有万事大吉。还需要增加配置项:

spring.mvc.pathmatch.matching-strategy=ant-path-matcher

这是因为 Springfox 假设 Spring MVC 的路径匹配策略是 ant-path-matcher,而 Spring Boot 2.5 以上版本的默认匹配策略是 path-pattern-matcher。


经过了这四步配置,swagger 和 springboot 的兼容问题就搞定了,下集再聊一下升级过程中其他的坑。

发布于: 刚刚阅读数: 3
用户头像

技术小生

关注

业务应用架构专家 2019-10-08 加入

主要负责公司内部系统的应用架构设计与落地。擅长Java语言开发,熟悉Python、Shell等。精通K8S等云原生相关技术。

评论

发布
暂无评论
SpringBoot升级所踩过的坑(一)_6月优质更文活动_技术小生_InfoQ写作社区