目录
一、Swagger与OpenApi
1.1 历史背景
1.2 版本区分
1.2.1 Swagger 2 vs OpenAPI 2
1.2.2 Swagger 3 vs OpenAPI 3
1.3 集成区别
1.3.1 集成 OpenAPI 2 (Swagger 2)
1.3.2 集成 OpenAPI 3 (Springdoc OpenAPI)
1.4 兼容性测试
1.4.1 Swagger2+OpenApi3
1.4.2 Swagger3的使用
1.4.3 Swagger3+OpenApi3
1.4.4 Swagger3增强-Knife4j集成测试
二、方案选择
一、Swagger与OpenApi
目前Api接口文档生成工具耳熟能详的属swagger了,后来的openapi这个概念和swagger有什么关系呢?
1.1 历史背景
Swagger:最初由 Reverb 公司开发,作为一个用于生成 API 文档的工具套件,旨在使 RESTful API 文档更加规范化和可视化。它包含了定义 API 结构的语言、工具和规范,最初是由 Swagger 规范(Swagger Specification)定义的。Swagger原本是一个由公司控制的工具集,虽然其规范广泛使用,但并没有正式的标准化机制。随着 OpenAPI Initiative 的成立,Swagger 变成了 OpenAPI 的工具之一。
OpenAPI:2016年,Swagger 的维护者将其交给了 OpenAPI Initiative(由 Linux 基金会管理)。因此,Swagger 规范从 Swagger 变成了 OpenAPI 规范(OAS)。OpenAPI 是 Swagger 规范的继任者,并成为正式的开放标准。OpenAPI 规范是广泛被接受的标准,用于描述 RESTful API。OpenAPI Initiative 提出了 OpenAPI 3 规范,作为对 Swagger 2 的继任者
即Swagger 是曾经的 API 规范,现在更多是作为 OpenAPI 规范的工具实现之一。OpenAPI 是 API 描述的正式标准,而 Swagger 是实现这个标准的一系列工具。Swagger 是工具和框架,OpenAPI 是标准规范。
1.2 版本区分
截止目前,能看到的版本有swagger2、swagger3、openapi2、openapi3、这些都有什么区别呢?
1.2.1 Swagger 2 vs OpenAPI 2
Swagger 2:这是 Swagger 规范的第二版,它主要作为工具和框架的名称存在。Swagger 2 定义了 API 文档的结构,并提供了工具来生成和展示文档,帮助开发人员更好地了解和使用 RESTful API。Swagger 2 和 OpenAPI 2 是同一个规范,Swagger 2 是 OpenAPI 2 的实现。
OpenAPI 2(也称为 Swagger 2):Swagger 2 规范在被 OpenAPI Initiative 收购并标准化后,成为了 OpenAPI 2 规范。这个版本继续沿用了 Swagger 2 的结构,只不过更改了它的名称。其实质上,它并没有引入太大的变动,更多的是进行了一些整理和标准化,使其成为了一个正式的开放标准。OpenAPI 2 基本定义了如何描述 API 路径、请求/响应、模型等。
即Swagger 2 和 OpenAPI 2 是同一版本的不同名称,Swagger 是实现工具,而 OpenAPI 是正式的标准。Swagger 2 = OpenAPI 2。
- 那为什么要改名呢(重要)?
Swagger 在行业中的广泛使用,它逐渐成为 API 描述的事实标准。然而,随着使用的普及,Swagger 已经不仅仅是一个工具,而是一个 API 规范的名称。为了让规范本身更加中立、独立于具体的工具和实现,Swagger 项目的维护团队决定将规范本身独立出来,并与工具实现分离。 为了推动 API 描述的标准化,OpenAPI Initiative 在 2016 年成立,并由 Linux Foundation 托管,目标是通过一个开放和中立的流程来制定和维护规范。Swagger 的原始规范被纳入到 OpenAPI Initiative 中,作为标准的基础。这个过程促使了规范的更新,并使其从单一的工具品牌中分离出来。 OpenAPI 作为标准名称,强调了其不依赖任何特定工具或公司,可以被任何工具和实现使用,这样更加符合开放标准的原则。通过将规范本身从 Swagger 品牌中分离出来,OpenAPI Initiative 为其他开发者和公司提供了一个开放的平台,使他们能够贡献、修改和改进这个标准。这不仅促进了规范的更快发展,还鼓励了不同社区和厂商的参与,使用 OpenAPI 这个名称避免了 "Swagger" 与某个特定公司或工具的关联,使得标准本身变得更加包容和中立。这样,OpenAPI 规范能够被更多的工具和实现所采用,而不局限于某一特定技术栈或公司。 Swagger 作为品牌与工具的名称,逐渐局限了规范的扩展和推广。OpenAPI 的命名将焦点转向了 API 描述规范 本身,而非某一单一工具。这个变更意味着不再强依赖 Swagger 工具链,其他工具(如 Springdoc OpenAPI、Redoc、Postman 等)也能更好地支持和推广该标准,而不需要受制于 Swagger 工具的设计。
随着 OpenAPI 规范的独立和标准化,越来越多的开发工具和语言支持了该规范。比如 Java、Python、Go 等各种语言都有基于 OpenAPI 的工具链,如 Swagger Codegen、OpenAPI Generator 等,能够根据 OpenAPI 规范生成代码、文档和客户端 SDK,Swagger 作为品牌和工具名称的局限性,在某种程度上阻碍了这一跨语言、跨平台的支持,而 OpenAPI 的出现则消除了这种障碍,促使了生态系统的多样性和开放性。
随着 OpenAPI 3 的发布,标准不仅在技术上得到了增强,而且在描述现代 API(例如复杂的认证、请求体、响应格式等)时变得更加灵活和强大。通过将 Swagger 2 变为 OpenAPI 3,规范更加适应了现代 API 的需求,能够更好地描述 微服务架构、多种认证方式、多种请求/响应格式 等新的设计理念。
即为了规范的独立性,标准化的推动,新版本的突破,跨平台支持而改名,OpenAPI 是一个更中立、开放和标准化的名称,它强调了 API 描述规范的独立性和跨平台支持,并能够适应未来 API 设计的需求。
1.2.2 Swagger 3 vs OpenAPI 3
Swagger 3:Swagger 3 是 OpenAPI 3 规范的实现工具版本。也就是说,Swagger 3 只是 Swagger 团队发布的一个实现,它实现了 OpenAPI 3 规范。Swagger 3 不是新的规范,它只是符合 OpenAPI 3 规范的一系列工具和框架。
OpenAPI 3:OpenAPI 3 是 OpenAPI 规范的最新版本,引入了大量的改进和新特性,目的在于提升 API 的描述能力和灵活性,支持更复杂的 API 设计。OpenAPI 3 标准完全不同于 OpenAPI 2,它在结构和语法上有很多变化。
即Swagger 3 是实现 OpenAPI 3 规范的工具,提供了与 OpenAPI 3 兼容的工具链。因此,OpenAPI 3 是最新的标准,而 Swagger 3 是基于该标准的工具实现。
最后,swagger2没被收购前是一种api规范,收购以后改了名字成了openapi2,即是规范又是工具,到了下一个版本swagger3就成实现openapi3规范的工具,不再是规范,降格。
1.3 集成区别
抛开业务代码和其他技术栈的干扰,新建一个只突出api生成工具的项目,Springboot版本为2.7.18。
1.3.1 集成 OpenAPI 2 (Swagger 2)
- 添加maven依赖
- 添加配置
- 添加文档
- 访问页面
启动 Spring Boot 应用后,通过 http://localhost:8080/swagger-ui.html 访问 Swagger UI,查看和测试 API。
注意:
1、springfox-swagger2 已不再维护,推荐迁移到 OpenAPI 3(即 Springdoc OpenAPI)。
2、测试项目使用的Springboot2.7.x,启动时会报这个错误:
Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
这个属于swagger2与Spring的版本兼容问题,在配置文件中加入如下配置,可以启动
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
参考:
Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException - 翎刿 - 博客园
1.3.2 集成 OpenAPI 3 (Springdoc OpenAPI)
注释掉swagger2相关代码
- 添加依赖
- 添加配置
- 添加文档
- 访问页面
访问路径:http://localhost:8080/swagger-ui.html(Springdoc OpenAPI 会自动集成 Swagger UI)或者http://localhost:8080/swagger-ui/index.html
API 文档:http://localhost:8080/v3/api-docs
springdoc-openapi 自动启用了 OpenAPI 3,默认情况下,它会根据 Spring 控制器自动生成 API 文档
从集成过程中可以看出,两个规范的实现差异化非常大,swagger2的groupId是io.springfox,到了openapi3就成了org.springdoc,文档生成用的注解和配置也不相同,比如swagger2用@ApiOperation,openapi3用@Operation,更多openapi3和swagger2的区别或者特性这里不再赘述,具体可以查看官网,这里只指出基础功能区别。
1.4 兼容性测试
Swagger2和openapi3的差异化太大,老项目使用swagger2,如果改成openapi3,迁移成本太大,尤其在文档生成的注解这块,就有很多,有什么办法可以做到兼容老版本?
1.4.1 Swagger2+OpenApi3
1.依赖共存(maven加上两个版本的依赖)
2.配置共存(OpenApiConfig.java与SwaggerConfig.java)
3.swagger文档放开(SwaggerApi.java),openapi3文档放开(OpenApi.java)
- 加入依赖
- 文档访问
属于openapi3风格的页面出来了,且默认使用的/v3/api-docs,swagger2的文档注解没生效,不符合兼容目的。说明openapi3不兼容swagger2
如果去掉swagger2的依赖,只保留openapi3的依赖,swagger2的配置和文档注解都报了引入依赖的错误。说明openapi3不集成swagger2
1.4.2 Swagger3的使用
在这里,先介绍下io.springfox:springfox-boot-starter:3.0.0 这个maven依赖.
这个从依赖的groupid可以看出,是swagger团队推出的swagger3,那既然OpenAPI 3规范已经有了Springdoc OpenAPI的实现,并且Swagger 的维护者将swagger交给了 OpenAPI Initiative?Swagger依然有更新呢?
实际上,springdoc-openapi-ui 和 springfox-boot-starter 都是为了在 Spring Boot 中集成 OpenAPI 3 提供支持的库,但它们来源不同、使用方式也不同,反映了两个不同的生态和实现方式。
Springdoc OpenAPI 是一个专门为 Spring Boot 提供 OpenAPI 3 支持的库,它是基于 OpenAPI 3 规范的现代化实现。springdoc OpenAPI 从一开始就明确支持 OpenAPI 3,并集成了 OpenAPI 3 的特性,因此它对 OpenAPI 3 进行了专门优化,并与 Spring Boot 深度集成。
Swagger 3 是由 Springfox 提供的一个基于 OpenAPI 3 规范的实现。虽然 Swagger 2 曾是主流的标准,但在 OpenAPI 3 发布后,Springfox 更新了其版本以支持 OpenAPI 3。Springfox 提供了一整套工具,包括 Swagger UI、Swagger Codegen 等,它支持 OpenAPI 3 规范,但并不像 Springdoc OpenAPI 那样专门针对 OpenAPI 3 进行优化。
Springfox 传统上一直是 Swagger 的实现库,Swagger 2 在 Spring 项目中被广泛使用。为了支持 OpenAPI 3,Springfox 更新了其版本(即 Swagger 3),保持了与 Swagger 2 的兼容性,但因为它的实现基于原先的 Swagger 2,配置和使用上相对复杂一些,自动化程度也没有 Springdoc OpenAPI 那么高。
也就是这个依赖是一个swagger2与openapi3的过渡版本。
- springfox-boot-starter出现后,会不会和Springdoc 同步发展
主要是出于向后兼容和用户需求的考虑。很多老的项目已经使用了 Swagger 2(或 Swagger 3)来生成 API 文档,并且它们没有立即迁移到 OpenAPI 3 或 Springdoc OpenAPI 的需求。为了让这些项目可以平滑过渡,Springfox 在其最新版本(即 springfox-boot-starter)中引入了对 OpenAPI 3 的支持,并且保持对 Swagger 2 的兼容。
Springfox 作为一个历史悠久的库,曾是 Swagger 2 的标准实现,直到现在它依然在很多旧项目中得到使用。然而,Springfox 最近的更新速度较慢,并且 Swagger 的维护已经停止,这导致 Springfox 在更新和适应 OpenAPI 3 的最新特性上显得比较滞后。尽管 springfox-boot-starter 能够支持 OpenAPI 3,且它依然会对一些 bug 进行修复,但由于其历史背景和与 Swagger 2 的兼容性,它将逐步成为一个较为老旧的库。它的未来更新频率较低,且主要集中在对现有功能的维护和一些小范围的修复上。不会像 Springdoc OpenAPI 那样快速发展。
Springfox 仍然会发布新版本,主要是对现有问题的修复和一些小范围的更新,但其发展速度较慢,并且已经不再是 OpenAPI 3 的最优选择。Springfox 可能会继续存在,但不会像 Springdoc OpenAPI 那样持续活跃发展。
Springfox 和 Springdoc 并没有直接的关系,它们是两个不同的项目,Springfox 不会与 Springdoc 同步发展。Springdoc OpenAPI 更专注于 OpenAPI 3 的标准,并且会保持快速迭代和更新,而 Springfox 更侧重于对现有项目的兼容性和旧版 Swagger 的支持。
了解了springfox-boot-starter这个依赖的作用后,进行集成测试,验证兼容性。
- 加入依赖
去除openapi3和swagger2的相关依赖,加入以下依赖
- 加入配置和文档注解
保留swagger2的配置和文档注解,保留OpenAPI 3文档注解,注释OpenAPI 3的配置,因为没有相关包,报错,文档注解是不报错的,说明这个过渡版本过渡功能有限。
- 访问页面
http://localhost:8080/swagger-ui/index.html
Swagger3确实做到了swagger2的兼容,同时支持openapi3的注解,但是页面怪怪的。虽然是OpenAPI 3 风格的输出,但标题错乱,且过渡功能不够完美。
1.4.3 Swagger3+OpenApi3
如果我同时加入openapi3的实现,springdoc的springdoc-openapi-ui依赖,加上openapi3的配置和注解。
访问页面后前后台都报错
java.lang.ClassNotFoundException:io.swagger.v3.oas.annotations.media.Schema$RequiredMode
加上openapi3的依赖,但不加openapi3的配置和注解
java.lang.IllegalStateException: Ambiguous handler methods mapped for '/v3/api-docs': {public org.springframework.http.ResponseEntity springfox.documentation.oas.web.OpenApiControllerWebMvc.getDocumentation(java.lang.String,javax.servlet.http.HttpServletRequest), public byte[] org.springdoc.webmvc.api.OpenApiWebMvcResource.openapiJson(javax.servlet.http.HttpServletRequest,java.lang.String,java.util.Locale) throws com.fasterxml.jackson.core.JsonProcessingException}
终归说明,swagger3与openapi3无法兼容
1.4.4 Swagger3增强-Knife4j集成测试
Knife4j是在swagger的基础上进行页面和功能的增强。有knife4j-openapi2、knife4j-openapi3等版本。官网:Knife4j · 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j
Knife4j版本参考:
Knife4j版本参考 | Knife4j
加入支持openapi2的依赖
启动报错
加入支持openapi3的依赖
访问:http://localhost:8080/doc.html ,报错:
java.lang.IllegalStateException: Ambiguous handler methods mapped for '/v3/api-docs': {public org.springframework.http.ResponseEntity springfox.documentation.oas.web.OpenApiControllerWebMvc.getDocumentation(java.lang.String,javax.servlet.http.HttpServletRequest), public byte[] org.springdoc.webmvc.api.OpenApiWebMvcResource.openapiJson(javax.servlet.http.HttpServletRequest,java.lang.String,java.util.Locale) throws com.fasterxml.jackson.core.JsonProcessingException}
Knife4j说兼容openapi3规范,而swagger3是实现了openapi3规范的,这两个一搭配,报错,说明knife4j在胡扯。knife4j-openapi2是支持swagger2的。knife4j-openapi3使用的是/v3/api-docs。
二、方案选择
从下面几条原因进行方案选择:
- swagger3不兼容knife4j,且是一个过渡版本,后续考虑到 Swagger 3 采用了 OpenAPI 3 标准,并且 Springfox 团队的更新频率和对新版本支持的速度相对较慢(与 springdoc-openapi 相比),这意味着 springfox-boot-starter 的长期可维护性可能存在问题。其生命周期可能会随着 Swagger 2 被淘汰而逐渐结束,特别是当 OpenAPI 3 完全替代 Swagger 2 之后。
- 还有一个比较有风险的问题是swagger3和Spring存在一些兼容问题,比如需要更改spring配置:spring.mvc.pathmatch.matching-strategy=ant_path_matcher。更改默认配置,可能造成Spring框架存在未知风险,而Api文档生成是非核心功能,不能因小失大。
- 项目集成openapi3遇到的问题
1.接口响应Base64编码,导致页面返回SyntaxError: Unexpected token 'e', "eyJvcGVuYX"... is not valid JSON
针对4.1.0版本接口响应Base64编码的情况 | Knife4j
解决:排除knife4j-openapi3中springdoc-openapi-ui中的高版本,新加一个低版本,从1.7.0改为1.6.9
参考:
SpringBoot 2.7.x 集成knife4j-openapi3 访问doc.html出现 Uncaught SyntaxError:Unexpected token ‘:‘_knife4j unexpected token '<', "<!doctype "... is n-CSDN博客
No OpenAPI resource found for group: swagger-config | Knife4j
或者添加转换器
https://github.com/springdoc/springdoc-openapi/issues/2143#issuecomment-1474981955
https://stackoverflow.com/questions/76235217/problem-displaying-swagger-ui-after-spring-library-update
2.Knife4j文档请求异常:Knife4j文档请求异常 | knife4j
解决:拦截器导致接口返回的“未登录”状态。需配置白名单
3.出现Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException的错误,这个就是knife4j与Spring的兼容问题
Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException - 翎刿 - 博客园
注意:集成实现openapi3时,关闭swagger2启用状态,即注释@EnableSwagger2注解
相关教程
springboot + springdoc-openapi + knife4j 集成案例:
https://juejin.cn/post/7214015651828006967
knife4j生产环境资源屏蔽:
knife4j生产环境资源屏蔽_knife4j.production-CSDN博客