Spring boot 2.0 升级到 3.3.1 的相关问题 (三)

Spring boot 2.0 升级到 3.3.1 的相关问题 (三)

Swagger 2 升级到 Springdoc-openapi 2.6.0

必须要升级,老的swagger使用的servlet-api,在JDK21的环境下已经不支持,启动会报错。java.lang.TypeNotPresentException: Type javax.servlet.http.HttpServletRequest not present

问题介绍

1、注解变动的问题。
原来的注解全部废弃了,需要全部使用新的注解。
2、配置变动的问题。
原来的配置方式全部失效,需要使用新的配置方式
3、项目中的注解如何批量迁移的问题。
编写工具,对所有的代码进行注解的转换。

解决方案

参考官方资料:https://springdoc.org/#migrating-from-springfox

废弃之前的所有swagger相关的依赖,改为引入springdoc-openapi-starter-webmvc-ui 依赖
   <dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
      <version>2.6.0</version>
   </dependency>

注意不要参考网上的其他例子引入springdoc-openapi-ui 这个依赖。

配置变动

原配置

//@Configuration
//@EnableSwagger2
@Slf4j
public class Swagger2Config {

    @Value(value = "${spring.profiles.active}")
    String environment;

    @Value(value = "${spring.application.name}")
    String applicationName;

    @Value(value = "${spring.application.version}")
    String applicationVersion;

    @Value(value = "${spring.application.controller.packages}")
    String[] controllerPackages;

    String applicationDescription;

    @Value(value = "${spring.application.description}")
    private void setApplicationDescription(String applicationDescription) {
        this.applicationDescription = "";
        if (StringUtils.isBlank(applicationDescription)) {
            return;
        }
        byte[] data = applicationDescription.getBytes(StandardCharsets.ISO_8859_1);
        this.applicationDescription = new String(data, StandardCharsets.UTF_8);
    }

        /**
         * 业务系统的固定请求头
         */
        public List<RequestParameter> getTokenPar() {
            RequestParameterBuilder tokenPar = new RequestParameterBuilder();
            List<RequestParameter> pars = new ArrayList<>();
            tokenPar
                .name(FrameConstant.HTTP_HEADER_AUTHORIZATION)
                .description("认证信息")
                .in(ParameterType.HEADER)
                .required(true)
                .build();
            pars.add(tokenPar.build());

            RequestParameterBuilder clientTypePar = new RequestParameterBuilder();
            clientTypePar.name(FrameConstant.HTTP_HEADER_CLIENT_TYPE)
                .description("客户端版本类型")
                .in(ParameterType.HEADER)
                .required(true)
                .build();
            pars.add(clientTypePar.build());
            RequestParameterBuilder clientVersionPar = new RequestParameterBuilder();
            clientVersionPar.name(FrameConstant.HTTP_HEADER_CLIENT_VERSION)
                .description("客户端版本号")
                .in(ParameterType.HEADER)
                .required(true)
                .build();
            pars.add(clientVersionPar.build());

            return pars;
        }


        @Bean
        public Docket createRestApi() {
            ApiSelectorBuilder builder = new Docket(DocumentationType.SWAGGER_2)
                .enable(("dev".equals(environment) || "test".equals(environment)))
                .apiInfo(apiInfo())
                .globalRequestParameters(getTokenPar())
                .select();
            if(controllerPackages!=null && controllerPackages.length >0){
                Stream.of(controllerPackages)
                    .map(RequestHandlerSelectors::basePackage)
                    .forEach(builder::apis);
            }
            Docket api = builder
                    .paths(PathSelectors.any())
                    .build();
            String serverServletContextPath = SpringContextUtil.getApplicationContext().getEnvironment().getProperty("server.servlet.context-path");
            if(StringUtils.isNotBlank(serverServletContextPath)){
                api.pathMapping(serverServletContextPath+"/");
            }
            return api;
        }

        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title(applicationName)
                    .description(applicationDescription)
                    .termsOfServiceUrl("http://")
                    .version(applicationVersion).build();
        }
}

新配置

/**
 * SpringDoc的配置
 */
@Configuration @Slf4j public class SpringDocConfig {

    @Value(value = "${spring.application.name}") String applicationName;

    @Value(value = "${spring.application.version}") String applicationVersion;

    @Value(value = "${spring.application.controller.packages}") String[] controllerPackages;

    String applicationDescription;

    @Value(value = "${spring.application.description}")
    private void setApplicationDescription(String applicationDescription) {
        this.applicationDescription = "";
        if (StringUtils.isBlank(applicationDescription)) {
            return;
        }
        byte[] data = applicationDescription.getBytes(StandardCharsets.ISO_8859_1);
        this.applicationDescription = new String(data, StandardCharsets.UTF_8);
    }

    //    @Bean
    //    @Profile("!prod")
    //    public OpenAPI customOpenAPI() {
    //        return new OpenAPI()
    //            .components(new Components()
    //                .addHeaders(FrameConstant.HTTP_HEADER_AUTHORIZATION, new Header().required(true).description("认证信息"))
    //                .addHeaders(FrameConstant.HTTP_HEADER_CLIENT_TYPE, new Header().required(true).description("客户端版本类型"))
    //                .addHeaders(FrameConstant.HTTP_HEADER_CLIENT_VERSION, new Header().required(true).description("客户端版本号"))
    //            )
    //            .info(new Info()
    //                .title(applicationName)
    //                .description(applicationDescription)
    //                .termsOfService("http://")
    //                .version(applicationVersion));
    //
    //    }
    @Bean @Profile("!prod") public GroupedOpenApi customOpenAPI() {
        return GroupedOpenApi.builder()
            .group(applicationName)
            .packagesToScan(controllerPackages)
            .addOperationCustomizer((operation, handlerMethod) -> {
                operation.addParametersItem(
                    new HeaderParameter().name(FrameConstant.HTTP_HEADER_AUTHORIZATION).description("认证信息")
                        .required(true));
                operation.addParametersItem(
                    new HeaderParameter().name(FrameConstant.HTTP_HEADER_CLIENT_TYPE).description("客户端版本类型")
                        .required(true));
                operation.addParametersItem(
                    new HeaderParameter().name(FrameConstant.HTTP_HEADER_CLIENT_VERSION).description("客户端版本号")
                        .required(true));
                return operation;
            }).addOpenApiCustomizer(openApi -> openApi
                .info(
                    new Info().title(applicationName).description(applicationDescription).version(applicationVersion)
                )
            )
            .build();
    }

}

注释掉的代码的方式也是可以的

批量注解转换工具

编写了一个独立的工具,使用JavaParser 来完成解析Java代码并修改更新Java的处理。最终将所有使用swagge2的注解的代码转换为SpringDoc的注解。

开源项目地址:https://gitcode.net/qiutongcunyi/swagger2springdoc-converter

该项目目前只做了我这边项目使用的一些注解的转换,如果你们有其他的注解需要转换,那么直接在这个项目基础上修改就可以了。

相关资料

SpringDoc官方文档:https://springdoc.org/#Introduction

### 关于 `com.baomidou` 和 Spring Boot 的版本兼容性 在讨论 `com.baomidou`(MyBatis-Plus)与 Spring Boot 的版本兼容性时,需注意 MyBatis-Plus 提供了一个启动器模块 `mybatis-plus-boot-starter` 来简化集成过程。该模块会自动适配特定版本的 Spring Boot。 #### 已知信息分析 1. 如果项目中存在方法缺失的情况(如 `isNotBlank` 方法),可能是由于 MyBatis-Plus 或其启动器版本之间的不匹配引起的[^1]。 2. 在某些情况下,Spring Boot 版本为 `2.2.6.RELEASE` 时,推荐使用的 MyBatis-Plus 版本为 `3.3.1`[^2]。 3. 当遇到类似 `com.baomidou.mybatisplus.core.mapper` 不存在的问题时,可能是因为使用了临时或不稳定版本(如 `3.3.1.tmp`)。官方建议更换至稳定版 `3.3.1`[^4]。 #### 推荐的版本组合 以下是基于社区反馈和官方文档总结的部分已验证兼容版本: | **Spring Boot** | **MyBatis-Plus** | |------------------|-------------------| | 2.0.x | 3.0.x | | 2.1.x | 3.1.x | | 2.2.x | 3.3.x | | 2.3.x | 3.4.x | | 2.4.x | 3.4.x 及以上 | 需要注意的是,随着 Spring Boot 和 MyBatis-Plus 的不断更新,新功能可能会引入新的依赖关系或移除旧的功能支持。因此,在升级过程中应仔细阅读两者的发布说明。 #### 解决方案 如果当前项目遇到了版本冲突问题,可以尝试以下措施: 1. 确认项目的实际需求并选择稳定的 MyBatis-Plus 版本。 2. 验证所选 MyBatis-Plus 版本是否已被标记为正式发布版本而非测试版本(如避免使用 `.tmp` 后缀版本)。 3. 使用 Maven 或 Gradle 锁定依赖版本,防止因仓库同步延迟导致的问题。 ```xml <!-- Maven 示例 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3</version> <!-- 替换为目标版本号 --> </dependency> ``` ```gradle // Gradle 示例 implementation &#39;com.baomidou:mybatis-plus-boot-starter:3.4.3&#39; // 替换为目标版本号 ``` #### 注意事项 当升级到更高版本的 Spring Boot 时,务必检查 MyBatis-Plus 是否提供了对应的兼容支持。例如,Spring Boot 2.4.x 引入了一些重要的上下文加载机制变更,这可能导致早期版本的 MyBatis-Plus 出现异常行为。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值