Beego框架+Swagger+API接口實現

Beego中Swagger實現API

1、安裝Beego

$ export GO111MODULE=on
$ export GOPROXY=https://goproxy.io
$ go get github.com/astaxie/beego
$ go get github.com/beego/bee

安裝完之後,bee 可執行文件默認存放在 $GOPATH/bin 裏面,所以需要把 $GOPATH/bin 添加到環境變量中

2、新建工程

bee new 工程名方法新建項目不同,生成api應用框架有特定的命令

(經測試,new生成的工程也可以實現路由接口,但是接口無法提交結構體字段,使用serverjson提交時無數據顯示,因此建議使用api生成框架,應用Swagger)

$ cd go/src                       #爲了在項目中使用go mod,在此文件下新建項目
$ bee api testapi(工程名)
├── conf
│   ├── app.conf                       //配置信息,需默認設置EnableDocs = true
├── controllers                          //控制器,負責處理項目邏輯
│   ├── object.go
│   └── user.go
├── lastupdate.tmp
├── main.go                              //主函數入口
├── models                               //數據模型
│   ├── object.go
│   └── user.go
├── routers                               //路由
│   ├── commentsRouter_controllers.go
│   └── router.go
├── swagger                            //自動化文檔,實現接口的定義
│   ├── favicon-16x16.png
│   ├── favicon-32x32.png
│   ├── index.html
│   ├── oauth2-redirect.html
│   ├── swagger.json
│   ├── swagger-ui-bundle.js
│   ├── swagger-ui-bundle.js.map
│   ├── swagger-ui.css
│   ├── swagger-ui.css.map
│   ├── swagger-ui.js
│   ├── swagger-ui.js.map
│   ├── swagger-ui-standalone-preset.js
│   ├── swagger-ui-standalone-preset.js.map
│   └── swagger.yml
├── testapi
└── tests
    └── default_test.go

運行命令

$ bee run -gendoc=true -downdoc=true

此處需要注意的是,api生成的工程和new生成的工程不同,api生成的工程默認從/go/src下讀取,因此工程新建時需要在src文件夾下新建,原因是工程不再使用go module控制依賴,因此如果需要兼容,需要在src文件下新建。否則會報錯找不到依賴。

運行成功後訪問:

http://127.0.0.1:8080/swagger/               #注意此處爲127.0.0.1,而不是localhost,涉及CORS跨域問題

3、設計接口,註解路由

swagger採用註解路由的方式實現接口,主要涉及兩個步驟:

3.1、設置routers/route.go

目前自動化文檔只支持如下的寫法的解析,其他寫法函數不會自動解析,即 namespace+Include 的寫法,而且只支持二級解析,一級版本號,二級分別表示應用模塊,自動化文檔採用CommentRouterPath對註解路由生成,Beego會在啓動的時候掃描文件生成路由,存放在routers下,具體內容如下:

  • API全局設置

    必須設置在 routers/router.go 中,文件的註釋,最頂部:

    全局的註釋如上所示,是顯示給全局應用的設置信息,有如下這些設置

    • @APIVersion
    • @Title
    • @Description
    • @Contact
    • @TermsOfServiceUrl
    • @License
    • @LicenseUrl
  • 路由設置

    只支持二級解析,一級版本號,二級分別表示應用模塊

//route.go

// @APIVersion 1.0.0
// @Title beego Test API
// @Description beego has a very cool tools to autogenerate documents for your API
// @Contact [email protected]
// @TermsOfServiceUrl http://beego.me/
// @License Apache 2.0
// @LicenseUrl http://www.apache.org/licenses/LICENSE-2.0.html
package routers

import (
	"github.com/astaxie/beego"
	"jingjinjiapi/controllers"
)

func init() {
	//add route
	ns := beego.NewNamespace("/v1",
		beego.NSNamespace("/object",
			beego.NSInclude(
				&controllers.ObjectController{},
			),
		),
		beego.NSNamespace("/user",
			beego.NSInclude(
				&controllers.UserController{},
			),
		),
	)
	beego.AddNamespace(ns)
}

路由設置後,經過後續步驟,可以通過訪問 http://127.0.0.1:8080/v1/user訪問user相關內容,原理類似。

3.2、controllers中註釋編寫

在控制器文件中下的每個controller中編寫函數,註釋寫在函數之上,註釋的內容就是我們要實現接口的功能。包括接口含義,傳遞參數,返回結果等。

  • @Title

    這個 API 所表達的含義,是一個文本,空格之後的內容全部解析爲 title

  • @Description

    這個 API 詳細的描述,是一個文本,空格之後的內容全部解析爲 Description

  • @Param

    參數,表示需要傳遞到服務器端的參數,有五列參數,使用空格或者 tab 分割,五個分別表示的含義如下

    1. 參數名
    2. 參數類型,可以有的值是 formData、query、path、body、header,formData 表示是 post 請求的數據,query 表示帶在 url 之後的參數,path 表示請求路徑上得參數,header 表示帶在 header 信息中得參數,body表示是一個raw數據請求,比如結構體的方式傳遞。
    3. 參數類型
    4. 是否必須
    5. 註釋
  • @Success

    成功返回給客戶端的信息,三個參數,第一個是 status code。第二個參數是返回的類型,必須使用 {} 包含,第三個是返回的對象或者字符串信息,如果是 {object} 類型,那麼 bee 工具在生成 docs 的時候會掃描對應的對象,這裏填寫的是想對你項目的目錄名和對象,例如 models.ZDTProduct.ProductList 就表示 /models/ZDTProduct 目錄下的 ProductList 對象。

    三個參數必須通過空格分隔

  • @Failure

    失敗返回的信息,包含兩個參數,使用空格分隔,第一個表示 status code,第二個表示錯誤信息

  • @router

    路由信息,包含兩個參數,使用空格分隔,第一個是請求的路由地址,支持正則和自定義路由,和之前的路由規則一樣,第二個參數是支持的請求方法,放在 [] 之中,如果有多個方法,那麼使用 , 分隔。

此處具體記錄幾個例子

3.2.1、POST+參數(body) + 直接訪問

post請求 http://127.0.0.1/v1/user , post內容爲models.User,作爲數據主體提交,結果返回user.id

// @Title CreateUser
// @Description create users
// @Param	body		body 	models.User	true		"body for user content"
// @Success 200 {int} models.User.Id
// @Failure 403 body is empty
// @router / [post]
func (u *UserController) Post() {
	var user models.User
	json.Unmarshal(u.Ctx.Input.RequestBody, &user)
	uid := models.AddUser(user)
	u.Data["json"] = map[string]string{"uid": uid}
	u.ServeJSON()
}

3.2.2、POST+參數(path)+提交內容(formData)

post請求 http://127.0.0.1/v1/user/{userid} ,post內容分兩部分,一部分爲path路徑上的參數,一部分爲提交的表單內容。

// @Title CreateUser
// @Description create users
// @Param	userid		path 	string	true		"user id"
// @Param	name		formData 	string	true		"user name"
// @Param	status		formData 	string	true		"user status"
// @Success 200 {string} success
// @Failure 403 error
// @router /:userid [post]
func (u *UserController) Post() {
	uid := u.GetString(":userid")
	//解析表單數據,兩種方法
	//1、GetString方法
	name := u.GetString("name")
	status := u.GetString("status")
	//2、beego提供的parseForm方法解析到結構體
	//定義接收結構體user
	//err := u.ParseForm(&user)
	u.Data["json"] = "delete success!"
	u.ServeJSON()
}

3.2.3、Get 直接訪問

Get請求http://127.0.0.1/v1/user/ Get所有user信息

// @Title GetAll
// @Description get all Users
// @Success 200 {object} models.User
// @router / [get]
func (u *UserController) GetAll() {
	users := models.GetAllUsers()
	u.Data["json"] = users
	u.ServeJSON()
}

3.2.4、Get+參數(path)

Get請求 http://127.0.0.1/v1/user/{uid} 獲取指定uid用戶信息

// @Title Get
// @Description get user by uid
// @Param	uid		path 	string	true		"The key for staticblock"
// @Success 200 {object} models.User
// @Failure 403 :uid is empty
// @router /:uid [get]
func (u *UserController) Get() {
	uid := u.GetString(":uid")
	if uid != "" {
		user, err := models.GetUser(uid)
		if err != nil {
			u.Data["json"] = err.Error()
		} else {
			u.Data["json"] = user
		}
	}
	u.ServeJSON()
}

3.2.5、Get+參數(query)

Get請求 http://127.0.0.1/v1/user/login?username=123&password=456 url上外加層級,並獲取查詢字段

// @Title Login
// @Description Logs user into the system
// @Param	username		query 	string	true		"The username for login"
// @Param	password		query 	string	true		"The password for login"
// @Success 200 {string} login success
// @Failure 403 user not exist
// @router /login [get]
func (u *UserController) Login() {
	username := u.GetString("username")                        // 區別於path,此處獲取沒有“:”
	password := u.GetString("password")
	if models.Login(username, password) {
		u.Data["json"] = "login success"
	} else {
		u.Data["json"] = "user not exist"
	}
	u.ServeJSON()
}

3.2.6、Put+參數(path)

Put請求 http://127.0.0.1/v1/user/{uid} 提交內容body,更新用戶信息。

// @Title Update
// @Description update the user
// @Param	uid		path 	string	true		"The uid you want to update"
// @Param	body		body 	models.User	true		"body for user content"
// @Success 200 {object} models.User
// @Failure 403 :uid is not int
// @router /:uid [put]
func (u *UserController) Put() {
	uid := u.GetString(":uid")
	if uid != "" {
		var user models.User
		json.Unmarshal(u.Ctx.Input.RequestBody, &user)
		uu, err := models.UpdateUser(uid, &user)
		if err != nil {
			u.Data["json"] = err.Error()
		} else {
			u.Data["json"] = uu
		}
	}
	u.ServeJSON()
}

3.2.7、Delete+參數(path)

Delete請求 http://127.0.0.1/v1/user/{uid} 提交內容uid,刪除用戶信息。

// @Title Delete
// @Description delete the user
// @Param	uid		path 	string	true		"The uid you want to delete"
// @Success 200 {string} delete success!
// @Failure 403 uid is empty
// @router /:uid [delete]
func (u *UserController) Delete() {
	uid := u.GetString(":uid")
	models.DeleteUser(uid)
	u.Data["json"] = "delete success!"
	u.ServeJSON()
}

其他相關設計原則可以參照上面內容。

3.3、生成自動化文檔

  • 配置文件設置 EnableDocs=true

  • 運行啓動命令

    $ bee run -gendoc=true -downdoc=true
    

    -gendoc=true 標識自動化的build文檔,-downdoc=true 自動下載swagger文檔查看器

  • 運行瀏覽器查看接口

    http://127.0.0.1/swagger

4、注意事項

  • route.go註解路由運行是通過CommentRouterPath解析的,會在同文件下生成commentsRouter_controllers.go文件,但需要注意工程必須在GOPATH路徑下,不然無法生成,也會無法匹配路由。
  • CORS問題

解決辦法:在main.go中將swagger集成到應用中

if beego.BConfig.RunMode == "dev" {
		beego.BConfig.WebConfig.DirectoryIndex = true
		beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章