文章目录
- Swagger学习(基于Go-Gin框架)
-
- 狂神说Swagger
-
- 小结
- 李文周Swagger
-
- Swagger介绍
-
- 第一步: 添加注释
- 第二步:生成接口文档数据
- 第三步:引入gin-swagger渲染文档数据
- 小结
- go中文文档中的Swaggo
-
- 介绍
- 使用
-
- 全局配置各项参数的作用
- 各个接口的注释参数作用
-
- `Tags`
- `Accept`
- `Produce`
- `Param`
-
- 参数类型
- 参数数据类型
- 是否是必须
- 参数描述
- 其他属性
- ```Success```
- Router
- 生成文档与测试
- 优化
- 如果使用了Token
- swag-go说明文档(git hub)
-
- 快速开始
- 支持的框架
- 声明式注释格式
-
- main.go上通用API信息
- 使用markdown描述
- API注释
- Mime类型
- 参数类型
- 数据类型
- 安全性
- 小结
- 参考资料
Swagger学习(基于Go-Gin框架)
在Swagger的学习中,我找了比较多的资料下面采取的学习路线是:
《狂神说Swagger》-> 李文周博客 -> 网上博主资料总结 -> 官方说明文档
只有第一个是视频,因为我感觉视频有一种手把手的教学的感觉,可以很好的让你入门,但是它有它的弊端,比如效率太低,讲的不够深入和全面等。
我个人认为学习一个技术,全面的了解过一遍,还是很有必要的,这是视频所无法给予的,所以后面的文档学习安排也是难度逐次递进的。
狂神说Swagger
在前端可以通过这种方式来伪造数据
Swagger号称世界上最流行的Api框架
RestFul APi文档在线自动生成工具=>api文档与api定义同步更新
可以直接运行在线测试api接口
小结
狂神说的swagger视频只是浅尝辄止了一下,也并没有讲的太深,带着我们把swagger入门了一下,不过我感觉这个教程的效果对于部分人而言可能不是很好,但是他提供了一个很好的学习的思路,他学习swagger是通过查看swagger包的源代码学习的,在没有很好的教程的时候,我们也可以采用这种方式去学习,但是这样的教程会感觉是在跳来跳去的,如果你的代码能力不是很精通的话,可能会对我们学习Swagger有附加的理解难度。
于是我就简单了解了一下,就跳过了这个视频的学习,不过也知道了一些基本的内容。
李文周Swagger
Swagger介绍
本质上是用JSON表示的RESTful API的接口描述语言。 Swagger包括自动文档,代码生成和测试用例生成。
在前后端分离的项目开发过程中,如果后端同学能够提供一份清晰明了的接口文档,那么就能极大地提高大家的沟通效率和开发效率。可是编写接口文档历来都是令人头痛的,而且后续接口文档的维护也十分耗费精力。
最好是有一种方案能够既满足我们输出文档的需要又能随代码的变更自动更新,而Swagger正是那种能帮我们解决接口文档问题的工具。
而我们以Gin框架为例,使用gin-swagger库,使用Swagger 2.0生成RESTful API文档
使用gin-swagger一般需要下面三个步骤:
- 按照swagger要求给接口代码添加声明式注释,具体参照声明式注释格式。
- 使用swag工具扫描代码自动生成API接口文档数据
- 使用gin-swagger渲染在线接口文档页面
第一步: 添加注释
在程序入口main函数上以注释的形式写下项目相关的介绍信息
这个算是全局配置,在swagger的最上面会显示出来,在实际的项目开发中,作用不是很大。
第二步:生成接口文档数据
使用下面的命令来安装swag工具
go get -u github.com/swaggo/swag/cmd/swag
在项目根目录执行以下命令来通过swag工具生成接口文档数据
swag init
执行完命令之后,如果我们之前的配置写的没有问题,项目根目录下会多出一个docs
文件夹。
./docs
├── docs.go
├── swagger.json
└── swagger.yaml
第三步:引入gin-swagger渲染文档数据
然后在项目代码中注册路由的地方按如下方式引入gin-swagger
相关内容:
import (// liwenzhou.com ..._ "bluebell/docs" // 千万不要忘了导入把你上一步生成的docsgs "github.com/swaggo/gin-swagger""github.com/swaggo/gin-swagger/swaggerFiles""github.com/gin-gonic/gin"
)
然后注册一下swagger api的路由(因为我们需要访问swagger的页面,它本质上也只是一个页面而已)
然后我们就需要注册一下swagger api相关路由了
r.GET("/swagger/*any", gs.WrapHandler(swaggerFiles.Handler))
这个时候,我们把项目运行起来,在访问http://localhost:8080/swagger/index.html
就能看到Swagger2.0 Api文档了。
小结
我觉得Q1mi(李文周)的教程算是一种提纲式的,略一遍的教程,但是并不很详细,只是入门起来够用,是那种20分钟就能看完的教程。
而且它很精简,精简到我做笔记只是把它的内容复制过来,相当于让自己有个印象而已。
go中文文档中的Swaggo
介绍
很多人不喜欢写api文档,不仅浪费大量的时间,而且无法保证面面俱到,但是api文档还是要有的,那么有没有一款工具能够根据我们的代码自动生成api文档呢? 让我们能够只专注于代码呢? 那就是swagger。
最后要呈现的文档效果大概如下:
使用
- 要使用swaggo,首先需要安装swag cli
go get -u github.com/swaggo/swag/cmd/swag
- 出来swag cli之外,我们还需要两个包
# gin-swagger 中间件
go get github.com/swaggo/gin-swagger
# swagger 内置文件
go get github.com/swaggo/gin-swagger/swaggerFiles
- 找到我们的入口函数(main函数)
首先需要import我们刚才安装的两个包,在原有import内,添加如下信息
import (ginSwagger "github.com/swaggo/gin-swagger""github.com/swaggo/gin-swagger/swaggerFiles"
)
全局配置各项参数的作用
然后main函数注释如下,另外需要在注册路由的地方,为swagger注册一下路由。
下面的注释中:
titile
:文档标题
version
:版本 (会在页面标题的右上角展示)
description,termsOfService,contact,info,license
: 这些都是一些注解,用来对swagger-ui界面上的一些信息进行描述,区别在于。
Info
注解是对swagger-ui界面上的基本信息进行描述,比如界面的标题,界面的介绍等。
Contact
注解是对swagger-ui界面上一些和接口有关的联系人的信息进行描述,包括但不限于开发人员名称,地址等。
License
注解是对swagger-ui界面上的一些和接口有关的服务条款或者使用的开源协议进行描述,包括服务名称,服务所在地址。
description
属性就是对界面做一个简单扼要的介绍,即用来描述界面是用来干什么的或者一些其他的注意事项等。
termsOfService
属性配置的是服务网站
host,BasePath
:如果你想直接swagger调试api,这两项需要填写正确,前者为服务文档的端口,ip,后者为基础路径,也就是你接口地址的前缀地址。
// @title Swagger Example API
// @version 1.0
// @description This is a sample server celler server.
// @termsOfService https://www.topgoer.com// @contact.name www.topgoer.com
// @contact.url https://www.topgoer.com
// @contact.email me@razeen.me// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html// @host 127.0.0.1:8080
// @BasePath /api/v1func main() {r := gin.Default()// 为swagger注册路由r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))v1 := r.Group("/api/v1"){v1.GET("/hello", HandleHello)// v1.POST("/login", HandleLogin)// v1Auth := r.Use(HandleAuth)// {// v1Auth.POST("/upload", HandleUpload)// v1Auth.GET("/list", HandleList)// }}r.Run(":8080")
}
- 如果注释写的没有问题,在main.go同目录下执行swag init
此时会自动生成文档,会发现在同目录下多出了一个docs文件夹,此时我们再引入这个文件夹,如下,然后就可以运行我们的项目,进入到swagger-ui里了。
此时会看到一个只有我们刚才写的配置信息的页面,其它的都没有。
- 为每个路由处理函数都加上注释
刚才我们只是在main函数上加了一下注释,相当于是配置了一下swagger的全局信息,而我们在项目中会写很多的接口,这每一个接口,也都需要一定的配置。
// @Summary 测试SayHello
// @Description 向你说Hello
// @Tags 测试
// @Accept json
// @Produce application/json
// @Param who query string true "人名"
// @Success 200 {string} string "{"msg": "hello Razeen"}"
// @Failure 400 {string} string "{"msg": "who are you"}"
// @Router /hello [get]
func HandleHello(c *gin.Context) {who := c.Query("who")if who == "" {c.JSON(http.StatusBadRequest, gin.H{"msg": "who are u?"})return}c.JSON(http.StatusOK, gin.H{"msg": "hello " + who})
}
各个接口的注释参数作用
Tags
用来给API分组
Accept
接收的参数类型支持表单(mpfd)和JSON(json)
Produce
返回的数据结构,一般都是使用json,其它支持如下:
Mime Type | 声明 |
---|---|
application/json | json |
text/xml | xml |
text/plain | plain |
html | html |
multipart/form-data | mpfd |
application/x-www-form-urlencoded | x-www-form-urlencoded |
application/vnd.api+json | json-api |
application/x-json-stream | json-stream |
application/octet-stream | octet-stream |
image/png | png |
image/jpeg | jpeg |
image/gif | gif |
Param
一般如下:
// 由参数名 参数类型 参数数据类型 是否必须 参数描述 其它属性构成
// @Param who query string true "人名"
参数类型
参数类型主要有三种:
-
path
:该类型的参数之间拼接在URL中// @Param id path integer true "文件ID"
-
query
:该类型的参数一般是组合在URL中// @Param who query string true "人名"
-
formData
:该类型参数一般是POST,PUT方法所用
// @Param user formData string true "用户名" default(admin)
path和query的区别在于:
query:user/john?password=*****
path:user/{username}
在query中,取出参数一般是键值对的形式存储,而path只是一个路径的拼接
参数数据类型
主要支持以下几种:
- string(stirng)
- integer(int,uint,uint32,uint64)
- number(float32)
- boolean(bool)
- file(file)
如果是上传文件的话,用file
类型,参数类型选择formData
是否是必须
声明该参数是否是必须需要的,必填的,值为true、false
参数描述
可以对此参数作一些说明
其他属性
除了上面的属性,还可以为该参数填写一些额外的属性,比如枚举,比如默认值,值范围等。如下:
枚举
// @Param enumstring query string false "string enums" Enums(A, B, C)
// @Param enumint query int false "int enums" Enums(1, 2, 3)
// @Param enumnumber query number false "int enums" Enums(1.1, 1.2, 1.3)值添加范围
// @Param string query string false "string valid" minlength(5) maxlength(10)
// @Param int query int false "int valid" mininum(1) maxinum(10)设置默认值
// @Param default query string false "string default" default(A)参数也可以组合使用
// @Param enumstring query string false "string enums" Enums(A, B, C) default(A)
Success
成功响应的数据。格式如下:
// @Success 1.Http响应码 {2.响应参数类型} 3.响应数据类型 4.其他描述
-
Http响应码:
例如200,400,500那些
-
响应参数类型/响应数据类型:
可以是自定义类型,也可以是Json类型,通常来讲我们都会使用自定义类型,返回一些我们指定的Json数据。
// @Success 200 {object} main.testStruct
可以在models文件夹中创建一个文件来存储所有的swagger返回json结构体
在注释上通过包名.struct
的方式即可找到,如果要返回struct数组,可以这样写:
// @Success 200 {anrry} main.File
如果返回的是json数据可以如下写:
// @Success 200 {string} json ""
然后可以在后面加一些对本结果的说明
Router
指定路由和HTTP方法,格式为:
// @Router /path/to/handle [HTTP方法]
不需要加basePath(基础路径)
生成文档与测试
当我们的配置写完之后,在main.go
下运行swag init
即可生成和更新文档,点击swagger-ui中的Try it out
即可测试,如果部分的API需要登录之后才能测试,可以Try
登录接口即可。
优化
在上面的操作进行过之后,已经可以使用了,但文档一般只是我们测试的时候需要,当我们的产品上线之后,就不需要让用户看到了,而且swaggo是之间build到二进制文件中的,带swaggo的包也会大很多。
解决方案就是在编译的时候通过build tag
来控制是否编译文档。
首先,在main.go
声明swagHandler
,并在该参数不为空时才加入路由:
package main//...var swagHandler gin.HandlerFuncfunc main(){// ...if swagHandler != nil {r.GET("/swagger/*any", swagHandler)}//...
}
同时,我们将该参数在另外加了build tag
的包中初始化
// +build docpackage mainimport (_ "github.com/razeencheng/demo-go/swaggo-gin/docs"ginSwagger "github.com/swaggo/gin-swagger""github.com/swaggo/gin-swagger/swaggerFiles"
)func init() {swagHandler = ginSwagger.WrapHandler(swaggerFiles.Handler)
}
之后我们可以通过go build -tags "doc"
来打包带文档的包,直接go build
来打包不带文档的包。
可以看到大小的差距。
如果使用了Token
如果我们在程序中使用了token中间键,只需要添加下面的注释即可:
// @Security x-token
// @param x-token header string true "Authorization"
swag-go说明文档(git hub)
快速开始
- 下载swag
$ go get -u github.com/swaggo/swag/cmd/swag# 1.16 及以上版本
$ go install github.com/swaggo/swag/cmd/swag@latest
- 在包含
main.go
文件的项目根目录运行swag init,这会解析注释并生成需要的文件(docs
文件夹和docs/docs.go
文件夹)
swag init
如果通用api注释没有写在main.go
文件中,也可以使用-g
标识符来告诉swag
swag init -g http/api.go
支持的框架
- gin
- echo
- buffalo
- net/http
声明式注释格式
main.go上通用API信息
注释 | 说明 | 示例 |
---|---|---|
title | 必填 应用程序的名称。 | // @title Swagger Example API |
version | 必填 提供应用程序API的版本。 | // @version 1.0 |
description | 应用程序的简短描述。 | // @description This is a sample server celler server. |
tag.name | 标签的名称。 | // @tag.name This is the name of the tag |
tag.description | 标签的描述。 | // @tag.description Cool Description |
tag.docs.url | 标签的外部文档的URL。 | // @tag.docs.url https://example.com |
tag.docs.description | 标签的外部文档说明。 | // @tag.docs.description Best example documentation |
termsOfService | API的服务条款。 | // @termsOfService http://swagger.io/terms/ |
contact.name | 公开的API的联系信息。 | // @contact.name API Support |
contact.url | 联系信息的URL。 必须采用网址格式。 | // @contact.url http://www.swagger.io/support |
contact.email | 联系人/组织的电子邮件地址。 必须采用电子邮件地址的格式。 | // @contact.email support@swagger.io |
license.name | 必填 用于API的许可证名称。 | // @license.name Apache 2.0 |
license.url | 用于API的许可证的URL。 必须采用网址格式。 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html |
host | 运行API的主机(主机名或IP地址)。 | // @host localhost:8080 |
BasePath | 运行API的基本路径。 | // @BasePath /api/v1 |
query.collection.format | 请求URI query里数组参数的默认格式:csv,multi,pipes,tsv,ssv。 如果未设置,则默认为csv。 | // @query.collection.format multi |
schemes | 用空格分隔的请求的传输协议。 | // @schemes http https |
x-name | 扩展的键必须以x-开头,并且只能使用json值 | // @x-example-key {“key”: “value”} |
使用markdown描述
如果文档中的短字符串不足以完整表达,或者需要展示图片,代码示例等类似的内容,则可能需要使用Markdown描述。要使用Markdown描述,请使用一下注释。
注释 | 说明 | 示例 |
---|---|---|
title | 必填 应用程序的名称。 | // @title Swagger Example API |
version | 必填 提供应用程序API的版本。 | // @version 1.0 |
description.markdown | 应用程序的简短描述。 从api.md 文件中解析。 这是@description 的替代用法。 |
// @description.markdown No value needed, this parses the description from api.md |
tag.name | 标签的名称。 | // @tag.name This is the name of the tag |
tag.description.markdown | 标签说明,这是tag.description 的替代用法。 该描述将从名为tagname.md的 文件中读取。 |
// @tag.description.markdown |
API注释
注释 | 描述 |
---|---|
description | 操作行为的详细说明。 |
description.markdown | 应用程序的简短描述。该描述将从名为endpointname.md 的文件中读取。 |
id | 用于标识操作的唯一字符串。在所有API操作中必须唯一。 |
tags | 每个API操作的标签列表,以逗号分隔。 |
summary | 该操作的简短摘要。 |
accept | API可以使用的MIME类型的列表。值必须如“Mime类型”中所述。 |
produce | API可以生成的MIME类型的列表。值必须如“Mime类型”中所述。 |
param | 用空格分隔的参数。param name ,param type ,data type ,is mandatory? ,comment attribute(optional) |
security | 每个API操作的安全性。 |
success | 以空格分隔的成功响应。return code ,{param type} ,data type ,comment |
failure | 以空格分隔的故障响应。return code ,{param type} ,data type ,comment |
response | 与success、failure作用相同 |
header | 以空格分隔的头字段。 return code ,{param type} ,data type ,comment |
router | 以空格分隔的路径定义。 path ,[httpMethod] |
x-name | 扩展字段必须以x- 开头,并且只能使用json值。 |
Mime类型
swag
接受所有格式正确的MIME类型, 即使匹配 */*
。除此之外,swag
还接受某些MIME类型的别名,如下所示:
Alias | MIME Type |
---|---|
json | application/json |
xml | text/xml |
plain | text/plain |
html | text/html |
mpfd | multipart/form-data |
x-www-form-urlencoded | application/x-www-form-urlencoded |
json-api | application/vnd.api+json |
json-stream | application/x-json-stream |
octet-stream | application/octet-stream |
png | image/png |
jpeg | image/jpeg |
gif | image/gif |
参数类型
- query
- path
- header
- body
- formData
数据类型
- string (string)
- integer (int, uint, uint32, uint64)
- number (float32)
- boolean (bool)
- user defined struct
安全性
注释 | 描述 | 参数 | 示例 |
---|---|---|---|
securitydefinitions.basic | Basic auth. | // @securityDefinitions.basic BasicAuth | |
securitydefinitions.apikey | API key auth. | in, name | // @securityDefinitions.apikey ApiKeyAuth |
securitydefinitions.oauth2.application | OAuth2 application auth. | tokenUrl, scope | // @securitydefinitions.oauth2.application OAuth2Application |
securitydefinitions.oauth2.implicit | OAuth2 implicit auth. | authorizationUrl, scope | // @securitydefinitions.oauth2.implicit OAuth2Implicit |
securitydefinitions.oauth2.password | OAuth2 password auth. | tokenUrl, scope | // @securitydefinitions.oauth2.password OAuth2Password |
securitydefinitions.oauth2.accessCode | OAuth2 access code auth. | tokenUrl, authorizationUrl, scope | // @securitydefinitions.oauth2.accessCode OAuth2AccessCode |
参数注释 | 示例 |
---|---|
in | // @in header |
name | // @name Authorization |
tokenUrl | // @tokenUrl https://example.com/oauth/token |
authorizationurl | // @authorizationurl https://example.com/oauth/authorize |
scope.hoge | // @scope.write Grants write access |
小结
之后看了看,感觉这个东西就是跟一个字典一样,既然如此我都复制粘贴过来也没什么意义。
链接如下,大家自己看吧。
参考资料
-
狂神说视频
-
李文周博客
-
Go中文文档
-
swag-go官方文档