Swagger 是什么
Swagger
是使用OpenAPI
规范(OAS)开发 API 的最广泛使用的工具生态系统。2015 年,SmartBear Software
将Swagger
规范捐赠给Linux Foundation
,并将规范重命名为OpenAPI
规范。 SmartBear
还成为OpenAPI Initiative(OAI)
的创始成员,该机构以开放和透明的方式管理OAS
的发展。
简而言之 Swagger 包含了一套 API 规范,并且提供一系列的生态组件
OpenAPI = 规范
Swagger = 实现规范的组件
Swagger 有什么用
Swagger
围绕着 API
诞生,它的用途也就是围绕着 API
- 作为 Rest API 的交互式文档
- 作为 Rest API 的形式化的接口描述
- 作为 Mock 服务的规范
- 作为调试文档生成测试页面 Petstore
Swagger 怎么用
YAML 编写
最为原始也最为可靠的方式就是人工编辑。Swagger
为我们提供了 Swagger 编辑器
,在线环境 Swagger Editor
OpenAPI 数据类型
常见数据类型 |
type |
format |
备注 |
integer |
integer |
int32 |
32 位有符号数 |
long |
integer |
int64 |
64 位有符号数 |
float |
number |
float |
|
double |
number |
double |
|
string |
string |
|
|
byte |
string |
byte |
Base64 编码 |
binary |
string |
binary |
|
boolean |
boolean |
|
|
date |
string |
date |
RFC3339 格式 |
dateTime |
string |
date-time |
RFC3339 格式 |
password |
string |
password |
页面隐藏输入 |
object |
object |
|
由上面的数据构成 |
OpenAPI 根对象
字段名称 |
类型 |
描述 |
openapi |
string |
必须 :版本号 |
info |
Info Object |
必须 :API 定义的元数据 |
servers |
[Server Object] |
服务器的列表信息 |
paths |
Paths Object |
API 路由配置 |
components |
Components Object |
组件 |
security |
[Security Requirement Object] |
安全 |
tags |
[Tag Object] |
标签信息 |
externalDocs |
External Documentation Object |
额外文档 |
关于对象的定义在 specification 处进行查看
编写API文档
Swagger
有两种编写格式,分别是 Json
和 Yaml
格式,个人更偏爱于 Yaml
格式,所以下文使用 Yaml
作为案例。
定义接口元信息
1 2 3 4 5 6 7 8 9 10 11
| title: 这是标题 【必填】 description: 这里是一段描述 termsOfService: API可以测试地址 contact: name: 联系人 url: http://www.example.com/support 联系人地址 email: support@example.com 联系人邮箱 license: name: Apache 2.0 授权信息 url: https://www.apache.org/licenses/LICENSE-2.0.html version: 1.0.1 OpenAPI的版本号【必填】
|
定义请求接口
1 2 3 4 5 6 7 8 9 10 11 12 13
| /pets: get: description: 这是一段描述信息 responses: '200': description: 又是一段描述 content: application/json: schema: type: array items: $ref: '#/components/schemas/pet'
|
从一个简单的请求接口定义,我们就看出来,最为核心的OPENAPI
包含的是 路径 /pets
,请求方式 get
, 请求响应 responses
,但是好像缺少了点什么?对的,我们还不知道怎么去定义 请求参数
。
定义请求参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| name: token in: header description: token to be passed as a header required: true schema: type: array items: type: integer format: int64
name: username in: path description: username to fetch required: true schema: type: string
name: id in: query description: ID of the object to fetch required: false schema: type: array items: type: string style: form explode: true
|
整合在一起
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| /pets: /# 路径,如果需要 path value 可以使用形如 /pets/{petId} get: /# get 请求,同理还有 put,post,delete,options 等方法 parameters: - name: token in: header description: token to be passed as a header required: true schema: type: array items: type: integer format: int64 - name: username in: path description: username to fetch required: true schema: type: string - name: id in: query description: ID of the object to fetch required: false schema: type: array items: type: string style: form explode: true description: 这是一段描述信息 responses: '200': description: 又是一段描述 content: application/json: schema: type: array items: $ref: '#/components/schemas/pet'
|
定义请求体
我们使用 requestBody
作为请求体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| description: user to add to the system content: 'application/json': schema: $ref: '#/components/schemas/User' examples: user: summary: User Example externalValue: 'http://foo.bar/examples/user-example.json' 'application/xml': schema: $ref: '#/components/schemas/User' examples: user: summary: User Example in XML externalValue: 'http://foo.bar/examples/user-example.xml' 'text/plain': examples: user: summary: User example in text plain format externalValue: 'http://foo.bar/examples/user-example.txt' '*/*': examples: user: summary: User example in other format externalValue: 'http://foo.bar/examples/user-example.whatever'
|
整合在一起
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| /pets: /# 路径,如果需要 path value 可以使用形如 /pets/{petId} get: /# get 请求,同理还有 put,post,delete,options 等方法 parameters: - name: token in: header description: token to be passed as a header required: true schema: type: array items: type: integer format: int64 - name: username in: path description: username to fetch required: true schema: type: string - name: id in: query description: ID of the object to fetch required: false schema: type: array items: type: string style: form explode: true requestBody: description: user to add to the system content: 'application/json': schema: $ref: '#/components/schemas/User' examples: user: summary: User Example externalValue: 'http://foo.bar/examples/user-example.json' 'application/xml': schema: $ref: '#/components/schemas/User' examples: user: summary: User Example in XML externalValue: 'http://foo.bar/examples/user-example.xml' 'text/plain': examples: user: summary: User example in text plain format externalValue: 'http://foo.bar/examples/user-example.txt' '*/*': examples: user: summary: User example in other format externalValue: 'http://foo.bar/examples/user-example.whatever' description: 这是一段描述信息 responses: '200': description: 又是一段描述 content: application/json: schema: type: array items: $ref: '#/components/schemas/pet'
|
直到这里,我们已经见过了 Request部分 header,query,path,body
如何组装。但是留在我们面前有一个小小的疑问,组件是什么?我们从下一章一窥究竟。
Schema 定义
我们知道我们的请求经常是特定的Json
格式,这个 Json
会出现在我们的 API
定义的各个部分,OPENAPI
为了解决我们需要不断的重写相同的 Json
定义,我们就有了Schema
的概念(当然也包含Map定义等)。
1 2 3 4 5 6 7 8 9 10 11 12
| type: object required: - name properties: name: type: string address: $ref: '#/components/schemas/Address' age: type: integer format: int32 minimum: 0
|
整合在一起
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| components: schemas: ErrorModel: type: object required: - message - code properties: message: type: string code: type: integer minimum: 100 maximum: 600 ExtendedErrorModel: allOf: - $ref: '#/components/schemas/ErrorModel' - type: object required: - rootCause properties: rootCause: type: string
|
小结
由于 OpenApi
的文档浩如烟海,这里就举了一个简单的例子,更多的时候还只能大家按图索骥的去查找自己想要的部分了。
Swagger 插件
最近的使用方式是使用 Swagger 插件
从代码直接生成,举个最为简单的例子,我们在 SpringBoot
项目中增加一个依赖
1 2 3 4 5
| <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency>
|
并且在添加一个配置
1 2 3 4 5 6 7 8 9 10 11 12
| @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build(); } }
|
这个时候我们访问 api-docs
我们就可以获得文档
1 2 3 4
| curl http://localhost:8080/spring-security-rest/api/v2/api-docs { //略 }
|
当是我们有了文档,一点都不具有可读性。很高兴的官方也提供了 UI
,继续添加
1 2 3 4 5
| <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.7.0</version> </dependency>
|
这个时候我们访问 http://localhost:8080/your-app-root/swagger-ui.html
我们就可以获得 页面了。
生态工具
参考资料