OAS (OpenAPI Specification)
OAS 是 OpenAPI Specification 的简称,可以翻译为OpenAPI规范,它是定义API的一种规范,定义了一种JSON格式或者YAML格式的API文档文件格式; 它的前身是Swagger规范。在2.0版本的时候OAS还冠有 Swagger 的印记,到了3.0版本就彻底去除了该释义。
Swagger 是一个 API文档维护组织,后来成为了 Open API 标准的主要定义者。目前可以认为Swagger3就是Open API 3.0
SpringFox 是 spring 社区维护的一个项目(非官方),践行OAS的一个项目,它将Swagger融合进流行的Spring框架,根据OpenAPI规范,帮助开发者自动生成API文档。
knife4j Knife4j 是为 Java MVC 框架集成 Swagger 生成 Api 文档的增强解决方案,前身是 swagger-bootstrap-ui
in short OAS 是标准规范, 前身是Swagger, Springfox 是具体的实现;
swagger2 和 OpenAPI 3 注解
swagger 文档 Knife4j 文档 请求注解 Knife4j 文档 响应注解
注意 swagger3 注解的包路径为io.swagger.v3.oas.annotations.*
| swagger2 | OpenAPI 3 | 注解位置 |
|---|---|---|
| @Api | @Tag(name = “接口类描述”) | Controller 类上 |
| @ApiOperation | @Operation(summary =“接口方法描述”) | Controller 方法上 |
| @ApiImplicitParams | @Parameters | Controller 方法上 |
| @ApiImplicitParam | @Parameter(description=“参数描述”) | @Parameters 里 |
| @ApiParam | @Parameter(description=“参数描述”) | Controller 方法的参数上 |
| @ApiIgnore | @Parameter(hidden = true) 或 @Operation(hidden = true) 或 @Hidden | - |
| @ApiModel | @Schema(description="") | DTO类上 |
| @ApiModelProperty | @Schema | DTO属性上 |
| @Hidden |
Spring Boot With knife4j 生成接口文档
https://doc.xiaominfo.com/docs/quick-start
knife4j (OpenAPI 3.0)
Knife4j在后面的版本中会全面切入OpenAPI3的规范中,因此在以后的版本迭代中,只会提供给OpenAPI3规范的适配,开发者应该尽快迁移到3的规范上来。 knife4j 4.0版本针对3的规范底层迁移使用springdoc-openapi项目,放弃springfox3.0
依赖
Spring Boot 2.x
...
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
<version>4.5.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-dependencies</artifactId>
<version>4.5.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>Spring Boot 3.x
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.0.0</version>
</dependency>配置
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import cn.hutool.core.util.RandomUtil;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.parameters.HeaderParameter;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.beans.factory.annotation.Value;
import java.util.ArrayList;
import java.util.List;
/**
* 文档页面 ./doc.html
* @author yang
*
*/
@Configuration
public class SwaggerConfig {
public static final String TOKEN_HEADER = "Authorization";
@Bean
public OpenAPI openApi() {
return new OpenAPI()
.components(
new Components().addSecuritySchemes(TOKEN_HEADER,
// 全局参数, 这里配置 bearer 后,你的请求里会自动在 token 前加上 Bearer
new SecurityScheme()
.type(SecurityScheme.Type.APIKEY)
.scheme("bearer")
.bearerFormat("JWT")
).addParameters(TOKEN_HEADER,
new Parameter()
.in("header")
.schema(new StringSchema())
.name(TOKEN_HEADER)
))
.info(
new Info()
.title("项目API文档")
// .description("项目API文档")
// 参考 Apache 2.0 许可及地址,你可以不配此项
// .license(new License().name("Apache 2.0").url("https://www.apache.org/licenses/LICENSE-2.0.html"))
.version("5.0")
);
}
}
public class SwaggerDataConfig {
@Schema
static class Page {
@Schema(name = "页码 (0..N)")
private Integer page;
private Integer size;
@Schema(name = "以下列格式排序标准:property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件:如:id,asc")
private List<String> sort;
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public List<String> getSort() {
return sort;
}
public void setSort(List<String> sort) {
this.sort = sort;
}
}
}knife4j 增强
https://doc.xiaominfo.com/docs/features/enhance
要使用Knife4j提供的增强,
knife4j.enable=true必须开启
| 属性 | 默认值 | 说明值 |
|---|---|---|
knife4j.enable | false | 是否开启Knife4j增强模式 |
knife4j.cors | false | 是否开启一个默认的跨域配置,该功能配合自定义Host使用 |
knife4j.production | false | 是否开启生产环境保护策略,详情参考文档 |
knife4j.basic | 对Knife4j提供的资源提供BasicHttp校验,保护文档 | |
knife4j.basic.enable | false | 关闭BasicHttp功能 |
knife4j.basic.username | basic用户名 | |
knife4j.basic.password | basic密码 | |
knife4j.documents | 自定义文档集合,该属性是数组 | |
knife4j.documents.group | 所属分组 | |
knife4j.documents.name | 类似于接口中的tag,对于自定义文档的分组 | |
knife4j.documents.locations | markdown文件路径,可以是一个文件夹(classpath:markdowns/*),也可以是单个文件(classpath:md/sign.md) | |
knife4j.setting | 前端Ui的个性化配置属性 | |
knife4j.setting.enable-after-script | true | 调试Tab是否显示AfterScript功能,默认开启 |
knife4j.setting.language | zh-CN | Ui默认显示语言,目前主要有两种:中文(zh-CN)、英文(en-US) |
knife4j.setting.enable-swagger-models | true | 是否显示界面中SwaggerModel功能 |
knife4j.setting.swagger-model-name | Swagger Models | 重命名SwaggerModel名称,默认 |
knife4j.setting.enable-document-manage | true | 是否显示界面中”文档管理”功能 |
knife4j.setting.enable-reload-cache-parameter | false | 是否在每个Debug调试栏后显示刷新变量按钮,默认不显示 |
knife4j.setting.enable-version | false | 是否开启界面中对某接口的版本控制,如果开启,后端变化后Ui界面会存在小蓝点 |
knife4j.setting.enable-request-cache | true | 是否开启请求参数缓存 |
knife4j.setting.enable-filter-multipart-apis | false | 针对RequestMapping的接口请求类型,在不指定参数类型的情况下,如果不过滤,默认会显示7个类型的接口地址参数,如果开启此配置,默认展示一个Post类型的接口地址 |
knife4j.setting.enable-filter-multipart-api-method-type | POST | 具体接口的过滤类型 |
knife4j.setting.enable-host | false | 是否启用Host |
knife4j.setting.enable-host-text | false | HOST地址 |
knife4j.setting.enable-home-custom | false | 是否开启自定义主页内容 |
knife4j.setting.home-custom-path | 主页内容Markdown文件路径 | |
knife4j.setting.enable-search | false | 是否禁用Ui界面中的搜索框 |
knife4j.setting.enable-footer | true | 是否显示Footer |
knife4j.setting.enable-footer-custom | false | 是否开启自定义Footer |
knife4j.setting.footer-custom-content | false | 自定义Footer内容 |
knife4j.setting.enable-dynamic-parameter | false | 是否开启动态参数调试功能 |
knife4j.setting.enable-debug | true | 启用调试 |
knife4j.setting.enable-open-api | true | 显示OpenAPI规范 |
knife4j.setting.enable-group | true | 显示服务分组 |
排序
分组排序 (Controller)
https://doc.xiaominfo.com/docs/features/tagSort
Controller之间的排序主要有两种方式,排序的规则是倒序,但是排序的最小值必须大于0
建议优先级是:@ApiSupport>@ApiSort>@Api
对于最高级别的值,可以从999开始 @ApiSupport注解自2.0.3版本引入
第一种,使用@ApiSupport注解中的属性order,代码示例如下:
@Api(tags = "2.0.3版本-20200312")
@ApiSupport(order = 284)
@RestController
@RequestMapping("/api/nxew203")
public class Api203Constroller {
}第二种情况,使用knife4j提供的增强注解@ApiSort,代码示例如下:
@Api(tags = "2.0.2版本-20200226")
@ApiSort(286)
@RestController
@RequestMapping("/api/nxew202")
public class Api202Controller {
第三种,使用注解@Api中的属性position(需要注意的是该属性以及过时,建议开发者使用第一种),代码示例如下:
@Api(tags = "2.0.2版本-20200226",position = 286)
@RestController
@RequestMapping("/api/nxew202")
public class Api202Controller {
}Knife4j也是通过Spring Plugin插件化的方式,扫描接口注解,最终通过扩展OpenAPI的扩展属性 tags[0].x-order进行赋值,最终在Ui界面中解析,然后再进行排序后渲染组件
- 但是 只有当Controller上的
@Tag注解同时填写name和description字段时,这个分组才会进入到tags字段中- 自Knife4j 4.0版本,开发者必须使用
knife4j-openapi2-spring-boot-starter组件才生效
接口排序 (RequestMapping)
Controller下的具体接口,排序规则是使用Knife4j提供的增强注解@ApiOperationSupport中的order字段,代码示例如下:
@ApiOperationSupport(order = 33)
@ApiOperation(value = "忽略参数值-Form类型")
@PostMapping("/ex")
public Rest<LongUser> findAll(LongUser longUser) {
Rest<LongUser> r=new Rest<>();
r.setData(longUser);
return r;
}Knife4j通过Spring Plugin插件体系,对每个接口进行扫描,最终将扫描的@ApiOperationSupport注解获取的order值通过OpenAPI的扩展属性规范进行赋值
最终在OpenAPI的规范中,接口的path节点下,通过x-order属性得到接口的排序,最终前端根据排序值进行排序
分组
/**
* GroupedOpenApi 是对接口文档分组,类似于 swagger 的 Docket
*/
@Bean
public GroupedOpenApi A_ProjectApi() {
return GroupedOpenApi.builder()
// 组名
.group("项目接口")
// 扫描的路径,支持通配符
.pathsToMatch("/api/**")
// 扫描的包
.packagesToScan("cn.simae.cloud.tny")
.build();
}
@Bean
public GroupedOpenApi B_AuthApi() {
return GroupedOpenApi.builder()
// 组名
.group("登陆接口")
// 扫描的包
.packagesToScan("cn.simae.cloud.admin.modules.security.rest")
.build();
}
@Bean
public GroupedOpenApi C_SysApi() {
return GroupedOpenApi.builder()
.group("框架接口")
.pathsToMatch("/api/**")
.packagesToScan("cn.simae.cloud.admin.modules")
.packagesToExclude("cn.simae.cloud.admin.modules.security.rest")
// 添加自定义配置,这里添加了一个用户认证的 header,否则 knife4j 里会没有 header
.addOperationCustomizer((operation, handlerMethod) -> operation.security(
Collections.singletonList(new SecurityRequirement().addList(TOKEN_HEADER)))
)
.build();
}配置
# 接口文档
knife4j:
enable: true
setting:
enable-debug: true
springdoc:
swagger-ui:
path: /swagger-ui.html
# 分组下的接口排序, 不配置 使用 Knife4j
# tags-sorter: alpha
# operations-sorter: alpha
# show-extensions: true
api-docs:
path: /v3/api-docs
enabled: true生产环境屏蔽
https://doc.xiaominfo.com/docs/features/accessControl
目前Springfox-Swagger以及Knife4j提供的资源接口包括如下:
| 资源 | 说明 |
|---|---|
| /doc.html | Knife4j提供的文档访问地址 |
| /v2/api-docs-ext | Knife4j提供的增强接口地址,自2.0.6版本后删除 |
| /swagger-resources | Springfox-Swagger提供的分组接口 |
| /v2/api-docs | Springfox-Swagger提供的分组实例详情接口 |
| /swagger-ui.html | Springfox-Swagger提供的文档访问地址 |
| /swagger-resources/configuration/ui | Springfox-Swagger提供 |
| /swagger-resources/configuration/security | Springfox-Swagger提供 |
springdoc以及Knife4j提供的资源接口包括如下:
| 资源 | 说明 |
|---|---|
| /doc.html | Knife4j提供的文档访问地址 |
| /v3/api-docs | springdoc提供的实例接口 |
| /v3/api-docs/swagger-config | springdoc提供的分组接口 |
| /v3/api-docs/** | 分组 |
| /swagger-ui/index.html | springdoc提供的文档访问地址 |
当我们部署系统到生产系统,为了接口安全,需要屏蔽所有Swagger的相关资源
如果使用SpringBoot框架,只需在application.properties或者application.yml配置文件中配置
knife4j:
# 开启增强配置
enable: true
# 开启生产环境屏蔽
production: true配置此属性后,所有资源都会屏蔽输出.