再见SpringFox,你好SpringDoc
前言
最近项目使用 SpringBoot 3 + Spring 6 搭建,接口文档准备一如既往的使用 Swagger 自动生成,引入 springfox-boot-starter
依赖,配置好相关的 Swagger 配置,结果启动报错,修改配置后启动不报错了,但是访问 swagger-ui/index.html 页面报404。
问题分析
一顿分析过后发现,最新的 springfox 3.0.0 (最后一次维护在2020年)仅支持 Spring 5.x,要想使用 springfox,最简单快捷的方式就是降版本,将 SpringBoot 的版本号从 3.x 修改为 2.7.x(或更低版本)。
新项目就是想体验最新的 SpringBoot 版本功能,这样一搞,岂不是本末倒置了,因此我就尝试了各种方法,企图通过修改 Spring Bean 属性等方式适配 Swagger ,结果发现 Spring 里面的对象属性是一层嵌一层,牵一发而动全身,菜鸡的我只好放弃。
企图尝试:
- 注册 WebMvcConfigurer Bean,重写
configurePathMatch(PathMatchConfigurer configurer)
方法。 - 在 PathMatchConfigurer 对象中,修改 patternParser 属性为 null ,再修改 pathMatcher 属性不为空,使得 patternParser 为空并且 preferPathMatcher 等于 true。
- 从而会影响 WebMvcConfigurationSupport#initHandlerMapping 方法的条件判断,进而影响 AbstractHandlerMapping 的 patternParser 属性为空,而 pathMatcher 不为空。
- AbstractHandlerMapping 的实例对象为 RequestMappingHandlerMapping ,其 afterPropertiesSet() 方法会根据 patternParser 属性作为条件判断,进而 RequestMappingInfo.BuilderConfiguration config 的 patternParser 属性为空并且 pathMatcher 属性不为空。
- RequestMappingInfo.DefaultBuilder#build() 方法会调用 RequestMappingInfo.BuilderConfiguration#getPatternParserToUse() 方法,该方法会返回上一步配置的 patternParser 属性。从而影响 build() 方法的条件判断,实例化 PatternsRequestCondition 对象,最后在实例化 RequestMappingInfo 对象时,pathPatternsCondition 为空,而 patternsCondition 不为空。
- 然后,springfox 的 WebMvcRequestHandler#getPatternsCondition() 方法会拿取 RequestMappingInfo 的 patternsCondition 属性,作为参数实例化 WebMvcPatternsRequestConditionWrapper 对象。
- 最后,WebMvcPatternsRequestConditionWrapper#getPatterns() 方法在使用 PatternsRequestCondition 属性时就不会出现空指针情况,程序正常启动。
问题突破
源码分析告一段落后,我就开始在网络遨游,寻找广大群众的力量,最终在 stackoverflow 上找到了解决方案,也是在此处第一次了解到 springdoc-openapi 。
先说解决方法的最核心东西,引入以下 maven 依赖。
1 | <dependency> |
注意:如果是 Spring Boot 1.x 或 2.x 的项目,springdoc-openapi 需要使用 1.x 的版本。
stackoverflow 帖子的链接地址:How to run Swagger 3 on Spring Boot 3
既然知道了可以使用 springdoc-openapi 解决,那就直接进入官方查看怎么使用。官方地址:springdoc.org
映入眼帘的介绍,让人为之心动,支持 SpringBoot 3 和 Swagger-ui !!!
使用SpringDoc Openapi
第一步,引入 maven 依赖。
第二步,同 Swagger 一样,编写配置类,主要是 GroupedOpenApi
和 OpenAPI
两个类,详见 从 SpringFox 迁移 。
1 |
|
如果项目仅有一个 GroupedOpenApi
配置类,那么可以直接配置在 application.properties 下,例如:
1 | springdoc.packagesToScan=package1, package2 |
第三步,对于 API Interface 和 API Model ,springdoc-openapi 与 swagger-annotation 略有不同,替换方案如下:
其中 @Schema
注解等同于 Swagger 的 @ApiModel
和 @ApiModelProperty
两个注解,不过在使用 @Schema
时需要注解,注解的 name 属性等同于 @ApiModel
的 value ,注解的 title 属性等同于 @ApiModelProperty
的 value 。
至此,springdoc-openapi 就配置完毕了,启动项目,访问 http://server:port/context-path/swagger-ui.html 。
springdoc-openapi 支持自定义访问路径,修改属性配置如下:
1 | # swagger-ui custom path |
修改后,访问 http://server:port/context-path/doc.html 也是一样的效果,它都会转发为最终的地址 http://server:port/context-path/swagger-ui/index.html 。