一、直击问题
解决前后顺序对比
解决方法:
在配置文件中添加排序规则方法sortTagsAlphabetically:
package com.example.demo.config;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.apache.commons.lang3.StringUtils;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Comparator;
import java.util.stream.Collectors;
@OpenAPIDefinition(
security = @SecurityRequirement(name = "Authorization")
)
@SecurityScheme(type = SecuritySchemeType.APIKEY, name = "Authorization", scheme = "Authorization", in = SecuritySchemeIn.HEADER)
@Configuration
public class OpenApiConfig {
private String title = "SpringDoc API";
private String description = "SpringDoc Application";
private String version = "v0.0.1";
@Bean
public OpenAPI springOpenAPI() {
return new OpenAPI()
.info(new Info()
.title(title)
.description(description)
.version(version));
}
@Bean
public GroupedOpenApi publicApi() {
return GroupedOpenApi.builder()
.group(title)
.pathsToMatch("/**")
.addOpenApiCustomiser(sortTagsAlphabetically())
.build();
}
public OpenApiCustomiser sortTagsAlphabetically() {
return openApi -> openApi.setTags(openApi.getTags()
.stream()
.sorted(Comparator.comparing(tag -> StringUtils.stripAccents(tag.getName())))
.collect(Collectors.toList()));
}
}
其他方法:如果你的项目可以升级,可以参考knife4j 的官方Issues 中的解决办法https://gitee.com/xiaoym/knife4j/issues/I5Z1YP
二、回顾历史
之前项目里一直用的都是springfox+knife4j来实现自动生成在线接口文档的,基本pom坐标如下:
<!-- Swagger2 核心依赖 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<!-- Swagger2 ui页面 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
<!--配合Swagger2 形成一个knife4j页面 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.4</version>
</dependency>
基本可以看出来,用的是swagger2
最新有个项目改成了springdoc +knife4j-springdoc-ui 的形式。项目集成pom坐标如下:
<!--swagger-->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.8</version>
</dependency>
<!--注意用的是 knife4j-springdoc-ui-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-springdoc-ui</artifactId>
<version>3.0.3</version>
</dependency>
关于knife4j-springdoc-ui 属于纯UI,没有之前用knife4j的一些增强功能,作者在gitee上对其进行了说明https://gitee.com/xiaoym/knife4j/issues/I4J6R7
当然如果很看好knife4j这款ui界面,可以直接集成knife4j-openapi3-jakarta-spring-boot-starter,是支持OpenAPI 3规范的,因为knife4j-springdoc-ui从做的gitee上来看,更多像是一个过渡产品
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
三、简介knife4j
作者在自己的代码仓库介绍到:knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名knife4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍knife4j的前身是swagger-bootstrap-ui,为了契合微服务的架构发展,由于原来swagger-bootstrap-ui采用的是后端Java代码+前端Ui混合打包的方式,在微服务架构下显的很臃肿,因此项目正式更名为knife4j
当然,我在swagger-bootstrap-ui就开始用了,一直觉得还不错,从最初觉得swagger-ui 的页面丑爆了,到因为这个UI页面慢慢接受了swagger项目地址https://gitee.com/xiaoym/knife4j
四、swagger2和swagger3
OpenAPI 3.0.0 是 OpenAPI 规范的第一个正式版本,因为它是由 SmartBear Software 捐赠给 OpenAPI Initiative,并在2015年从 Swagger 规范重命名为 OpenAPI 规范。
OpenAPI 规范 (中文版)地址:https://openapi.apifox.cn/
swagger 是一个 api 文档维护组织,后来成为了 Open API 标准的主要定义者,现在最新的版本为17年发布的 Swagger3(Open Api3)。
swagger2于17年停止维护,现在最新的版本为 Swagger3(Open Api3)。
swagger2 遵循的是 OpenAPI 2 规范
swagger3 遵循的是 OpenAPI 3 规范
springfox 和 Springdoc
- SpringFox是 spring 社区维护的一个项目(非官方),一般集成swagger2 用的多
- SpringDoc也是 spring 社区维护的一个项目(非官方),集成swagger3 用的多
SpringDoc支持swagger页面Oauth2登录(Open API3的内容),相较 SpringFox来说,它的支撑时间更长,无疑是更好的选择。但由于国内发展较慢,在国内不容易看到太多有用的文档,不过可以访问它的官网。它的使用了 swagger3(OpenAPI3),但 swagger3 并未对 swagger2 的注解做兼容,不易迁移,也因此,名气并不如 spring fox。
SpringFox | SpringDoc |
@Api | @Tag |
@Apilgnore | @Parameter(hidden = truelor@Operation(hidden = true)or@Hidden |
@ApilmplicitParam | @Parameter |
@ApilmplicitParams | @Parameters |
@ApiModel | @Schema |
@ApiModelProperty | @Schema |
@ApiOperation(value = "foo", notes = "bar") | @Operation(summary = "foo", description ="bar") |
@ApiParam | @Parameter |
@ApiResponse(code = 404.message = "foo") | @ApiResponse(responseCode ="404", description = "foo") |
五、解读Springdoc
官网地址:https://springdoc.org/
springdoc-openapi 其实就是swagger3 ,是swagger团队在将swagger 将其作品捐献给开源的啥来着,后来就改名叫这个springdoc了
SpringDoc是一款可以结合SpringBoot使用API文档生成工具,基于OpenAPI 3,而且项目维护和社区都在不断更新,不仅支持SpringMVC,而且还支持Spring WebFlux项目。
官网架构图如下,可以清晰的认知springdoc-openapi-ui 所在的层级
如果没有用到knife4j ,单纯的springdoc-openapi 的UI页面查看接口,那就更简单了直接修改配置文件,添加排序方法,但是这个排序对于knife4j 是不起作用的,因为是个前端js排序,只对http://localhost:8080/swagger-ui/index.html生效。
对于http://localhost:8080/doc.html暂时只能在java 端排序好进行返回,后面会具体分析
springdoc:
api-docs:
#是否开启文档功能,默认为true,可不配置
enabled: true
swagger-ui:
# 访问ip:host/api,可直接访问Swagger springdoc
path: /api
# API 排序
tags-sorter: alpha
# HTTP 方法排序
operations-sorter: method
不重写排序返回的分组是随机的
配置swagger-ui 的tags-sorter是前台排序,访问http://localhost:8080/swagger-ui/index.html
查看网络请求返回数据:会看到我们在yml里面配置好的排序规则
查看排序规则,会发现返回的tags 顺序和实际页面显示的顺序并不一致,因为我们在配置文件设置的tags-sorter生效了
来证明对于knife4j 无效,访问 http://localhost:8080/doc.html,可以发现页面排序完全和返回tags一致
对http://localhost:8080/swagger-ui/index.html 进行F12 查看网页源代码,可知这里调用了js 的字符串排序方法
参考官方文档 https://springdoc.org 的 5.2 swagger-ui properties 可知,有以下2个配置项可供我们给 API 和 HTTP 方法排序:
- springdoc.swagger-ui.tagsSorter 给 API 排序, 如果其值为 alpha 就表示按字母顺序排序。默认情况下(也就是不配置此项),API 的顺序由 swagger 自己决定(也就是没什么顺序);
- springdoc.swagger-ui.operationsSorter 给 HTTP 方法排序,其值为 alpha 同样表示按字母顺序排序,值为 method 表示根据 HTTP 请求的类型(顺序如下:DELETE > GET > POST > PUT)排序。默认情况下,Controller 代码里面,你写的是什么顺序,swagger 就给你展示什么顺序。
翻译过来就是:对每个API的标记列表应用排序。它可以是‘’alpha'(按字母数字路径排序)或函数(参见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort,了解如何编写排序函数)。每次传递都将两个标记名字符串传递给排序器。默认值是由Swagger UI确定的顺序。