在传统的前后端分离的项目中,会使用接口文档来统一前后端的接口,一个接口应该包含以下信息:
其实接口文档除了要包含这些信息以外,可能还需要有一些代码示例以及参数的示例,毕竟有时候干巴巴的文字看起来很难懂。
在前后端分离的项目开发过程中,如果后端开发人员能够提供一份清晰明了的接口文档,那么就能极大地提高前后端开发人员的沟通效率和开发效率。可是编写接口文档历来都是令人头痛的,而且后续接口文档的维护也十分耗费精力。最好是有一种方案能够既满足我们输出文档的需要又能随代码的变更自动更新,而Swagger正是那种能帮我们解决接口文档问题的工具。
以Gin框架为例,使用gin-swagger库,使用Swagger 2.0生成RESTful API文档。项目的demo代码地址:https://gitee.com/Free_Software/swagger-go。
使用gin-swagger一般需要下面三个步骤:
在程序入口main函数上以注释的方式写下项目相关介绍信息。
// @title blogWebsite
// @version 2.0
// @description 这是一个blogWebsite的demo项目,最初用来练习docker compose。目前项目中有很多接口还没有开发完成
// @termsOfService http://swagger.io/terms/
// @contact.name 氷
// @contact.url http://www.swagger.io/support
// @contact.email [email protected]
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host 127.0.0.1:8080
// @BasePath /
在你代码中处理请求的接口函数(通常位于controller层)按如下方式写上注释。
type responseUser struct {
Msg string
Id uint64
}
// AddUser
// @Summary 添加用户接口
// @Description 从前端获取用户名和密码用来添加一个用户
// @Tags 用户管理
// @Accept application/json
// @Produce application/json
// @Param username query string true "用户名"
// @Param password query string true "密码"
// Success 200 {object} responseUser
// @Router /addUser [post]
func AddUser(c *gin.Context) {
username := c.Query("username")
password := c.Query("password")
//查询用户名和密码是否为空
if username != "" && password != "" {
//查询用户名是否重复
result := service.SelectUserIfExist(username)
if result == 1 {
res := responseUser{
Msg: "用户名已被使用",
}
c.JSON(http.StatusOK, res)
} else {
id := service.Register(username, password)
res := responseUser{
Msg: "用户注册成功",
Id: id,
}
c.JSON(http.StatusOK, res)
}
} else {
res := responseUser{
Msg: "用户名或密码不能为空",
}
c.JSON(http.StatusOK, res)
}
}
type responsePost struct {
Msg string
Id uint64
}
// AddPost
// @Summary 添加文章接口
// @Description 从前端获取文章标题,文章内容和用户ID用来添加文章
// @Tags 文章管理
// @Accept application/json
// @Produce application/json
// @Param title query string true "文章标题"
// @Param context query string true "文章内容"
// @Param userID query string true "用户ID"
// @Success 200 {object} responsePost
// @Router /addPost [post]
func AddPost(c *gin.Context) {
title := c.Query("title")
context := c.Query("context")
userID := c.Query("userID")
id, err := strconv.Atoi(userID) // 将字符串类型的id转换为int类型
if err != nil {
fmt.Println("Error:", err)
return
}
if title != "" {
result := service.AddPost(title, context, id)
responsePost := responsePost{
Msg: "添加文章成功",
Id: result.PostID,
}
c.JSON(http.StatusOK, responsePost)
} else {
responsePost := responsePost{
Msg: "文章标题不能为空",
}
c.JSON(http.StatusOK, responsePost)
}
}
编写完注释后,使用以下命令下载和安装swagger的cmd命令:
go install github.com/swaggo/swag/cmd/swag@latest
在项目根目录执行以下命令,使用swag工具生成接口文档数据。
swag init
执行完上述命令后,如果你写的注释格式没问题,此时你的项目根目录下会多出一个docs文件夹。
./docs
├── docs.go
├── swagger.json
└── swagger.yaml
下载gin-swagger的相关包
go get -u github.com/swaggo/gin-swagger
go get -u github.com/swaggo/files
在项目代码中注册路由的地方按如下方式引入gin-swagger相关内容。
// 这是你的注册路由的文件
import (
_ "docker_compose_blog/docs" // 千万不要忘了导入把你上一步生成的docs文件夹的路径
swaggerFiles "github.com/swaggo/files"
gs "github.com/swaggo/gin-swagger"
)
注册swagger api相关路由
// 在你注册路由的文件中添加
r.GET("/swagger/*any", gs.WrapHandler(swaggerFiles.Handler))
把你的项目程序运行起来(重新go build,然后再运行),打开浏览器访问 http://localhost:8080/swagger/index.html 就能看到Swagger Api文档了。
需要注意的是:每次修改注释后都必须要重新swag init然后go build,修改才会生效。
这是main函数上面注释生成的项目描述信息。
由于有两种Tags(文章管理和用户管理),相同的Tags会被分为一类。如下所示:
先在用户管理中添加一个用户。点击Try it out就可以输入用户名和密码。
点击Execute就可以提交请求,可能会遇到跨域问题,请自行解决。最后返回结果如下:
现在测试文章管理的接口。测试结果如下:
查询数据库,发现一切正常。
如果前后端在交互过程中涉及到token的传递,那么会有以下几种情况。
# 前端发送axios
axios.delete(`http://127.0.0.1:8080/admin/deleteBlog?title=${row.id}&token=${token}`)
# 后端的注释
// @Param token query string true "Token"
# 前端发送axios
const token = localStorage.getItem('token');
const response = await axios.get('http://127.0.0.1:8080/admin/getPubTimeData', {
headers: {
Authorization: `Bearer ${token}`,
}
# 后端在接口注释中要添加以下内容
@Security ApiKeyAuth
# 接下来需要在swagger.yaml文件中写入以下内容(里面的ApiKeyAuth这个名字需要和@Security注释后面的内容保持一致)
securityDefinitions:
ApiKeyAuth:
type: apiKey
in: header
name: Authorization
以上就完成了swagger的基本使用。其实关于Swagger还有很多东西,这是一个中文文档:SwaggerGo中文文档。下面是一些官方文档中比较常见注释的解释。
注释 | 描述 |
---|---|
Accept | Accept字段仅适用于带有request body的请求,例如POST、PUT和PATCH。只有使用这些请求方法的接口才需要定义接收的 MIME 类型列表。 |
Produce | 定义接口返回的 MIME 类型列表。 |
注释 | 描述 |
---|---|
@Summary | 接口功能的简要概述。 |
@Description | 接口的详细说明。 |
@Tags | 接口的标签列表,可以有多个标签,每个标签用英文的逗号分隔。这样接口会按照标签进行分类。 |
@Param | 接口接收的数据,参数用空格分隔。参数分别是:“参数名” “参数类型” “数据类型” “是否必须” “参数的描述”。 |
@Success | 接口的成功响应语法格式:“响应的状态码” “数据类型” “返回对象模型” “描述信息”。 |
@Failure | 接口的故障响应语法格式:“响应的状态码” “数据类型” “返回对象模型” “描述信息”。 |
@Response | 与@Success和@Failure的作用相同。 |
@Router | 接口的路由定义,用空格隔开路径和请求方法。 path [httpMethod] |
@Security | 定义接口的安全性 |
别名 | 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 |