赞
踩
必须要升级,老的swagger使用的servlet-api,在JDK21的环境下已经不支持,启动会报错。java.lang.TypeNotPresentException: Type javax.servlet.http.HttpServletRequest not present
1、注解变动的问题。
原来的注解全部废弃了,需要全部使用新的注解。
2、配置变动的问题。
原来的配置方式全部失效,需要使用新的配置方式
3、项目中的注解如何批量迁移的问题。
编写工具,对所有的代码进行注解的转换。
参考官方资料:https://springdoc.org/#migrating-from-springfox
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。