『Beego + Swagger 快速上手』

wuxiaoshen發表於2018-02-24

大綱

  • Beego 是什麼
  • 為什麼寫這個
  • 如何指導

前幾天我寫了一個Swagger 上手指南,覺得還是讓使用者難以上手。儘管它是一款優秀的API 工具。

但我在編寫API 的過程中發現幾個問題:

  • 編寫繁瑣:儘管會提示出關鍵字,但是不支援 yaml 自動換行,自動對齊等功能
  • 儲存不方便: 儘管可以到處yaml 或者json 格式的配置檔案,但要是API 發生變更,又需要重新開啟下載的包,或者線上版的Editor
  • 不極客:Swagger 是給程式設計師使用的,但是單純的配置檔案,程式設計師不太喜歡,而是喜歡那種程式設計實現的API,比如在本地可以及時訪問,即使是變更也能立馬看到效果

好,基於上面三點。我進行了探索:

  • 第一:使用Swagger 外掛

我一直很喜歡JetBrains 旗下的開發工具,樣樣皆上精品。各種主流的程式語言都有對應的整合開發環境,即使是隻使用其中的一款,外掛豐富,也能實現其他程式語言的程式設計。

Settings --> Plugins --> Swagger Plugins || Swagger Codegen

下載上述兩個外掛,即可在本地編寫yaml 格式的Swagger配置檔案,左邊配置,右邊視覺化。

這樣可以本地實現配置檔案的編寫,實現API 的編寫。

Swagger.png

  • 第二:使用Beego 框架

beego 是一個快速開發 Go 應用的 HTTP 框架,他可以用來快速開發 API、Web 及後端服務等各種應用,是一個 RESTful 的框架,主要設計靈感來源於 tornado、sinatra 和 flask 這三個框架,但是結合了 Go 本身的一些特性(interface、struct 嵌入等)而設計的一個框架。

其中一個功能是自動化文件,讓使用者快速的編寫API。

即:可以程式設計實現API。

下面的文章即是:如何實現使用Beego + Swagger 快速開發API.

接著上回的文章Swagger 上手指南 , 我在文章多次提出Http 請求包含哪些知識?

  • Http 動作
  • URL 路徑
  • Body 體
  • Response 響應

即:根據不同的 Http 動作,訪問URL 路徑,定位資源,服務端根據請求,將資源進行返回給使用者的這麼一個過程。

  • 前提:理解 Beego 框架

Beego 採用典型的MVC框架:即M(models)、V(views)和C(controllers)

  • M 層定義資料,表及結構體等
  • V 層定義視覺化層,即前端展現出現的頁面,這裡我們只需下載Swagger即可使用前端檔案
  • C 層處理業務邏輯,比如API 中的POST,PUT,GET, DELETE 等

一個典型的Beego 框架的目錄大概是這樣的:

├── conf
│   └── app.conf
├── controllers
│   ├── admin
│   └── default.go
├── main.go
├── models
│   └── models.go
├── static
│   ├── css
│   ├── ico
│   ├── img
│   └── js
└── views
    ├── admin
    └── index.tpl

複製程式碼

使用Beego + Swagger 編寫API 的過程中,我們只需關注這些檔案:

  • routers 定義Http URL 路徑

  • models 定義請求體Body 和響應 Response

  • controllers 處理Http 請求動作:POST、PUT、DELETE、GET等

  • 使用的到的工具:

go get github.com/astaxie/beego

go get github.com/beego/bee

beego 即:beego 庫檔案,不懂環境配置看文章 Go 語言專欄第一期

bee 即: 命令列工具,這個很好理解,go 也有命令列工具,這些都是方便建立和管理相關專案的命令列(最近也在工作中開發一個命令列工具,有時間聊聊)

開始

  • 建立API 專案

bee api apiTest

在 src (go專案環境變數下) 新建了一個apiTest 資料夾,裡面預設存在一些預設的API 檔案

  • 自動下載Swagger檔案,自動化文件,即可在本地瀏覽預設API: http://8080/swagger

bee run -gendoc=true -downdoc=true

生成的 API 檔案目錄大概這樣:

├── conf
│   └── app.conf
├── controllers
│   └── object.go
│   └── user.go
├── docs
│   └── doc.go
├── main.go
├── models
│   └── object.go
│   └── user.go
├── routers
│   └── router.go
└── tests
    └── default_test.go
複製程式碼

各檔案作用

  • main.go 函式入口
  • models 對應的API 中涉及的body 和 response
  • routers 路由設定:即URL 路徑
  • controllers 對應URL 的動作發生和響應的處理
  • app.conf 配置檔案

主要處理:models 、contorlers 和 routers 三個檔案。

核心思路:關注這三點:http 動作、請求、以及返回響應;無需關注具體的處理邏輯,一律使用 Fake 資料

示例:

實現下面這個例子:

例子:


POST  /api/v1.0/designer/paas/{paasid}
Request
{
  "git": {
    "addr":"ssh://ipaddr/path/.git",
    "branch":"master"
  }
}

Normal response codes: 201
{
    "passid":"xxxxx",
    "local_git":"ssh://localhost/paasdata/confcenter/{paasid}/pdmng/.git"
}

Error response codes: 400
{
    "desc": "error reason"
}

GET /api/v1.0/designer/paas/{paasid}?field=detail
Request: None

Response:
201
{
    "passid":"xxxxx",
    "local_git":"ssh://localhost/paasdata/confcenter/{paasid}/pdmng/.git"
}
400
{
    "status": "no exist {paasid}"
}

PUT /api/v1.0/designer/paas/{paasid}
Request:
{
  "git": {
    "addr":"ssh://ipaddr/path/.git",
    "branch":"master"
  }
}

Normal response codes: 201
{
    "passid":"xxxxx",
    "local_git":"ssh://localhost/paasdata/confcenter/{paasid}/pdmng/.git"
}

Error response codes: 400
{
    "status": "error reason"
}

DELETE /api/v1.0/designer/paas/{paasid}
Request None

Response 201:
{
    "status": "success"
}

400:
{
    "status": "no exist the paasid"
}
複製程式碼

前面我們已經知道了,結合Beego 和 Swagger 編寫API 的重點是在編寫 models 和 controllers: models 編寫引數、響應 即:定義各種各種的結構體和編寫具體的函式

controllers 編寫具體的http 動作請求和響應 即:定義具體的引數型別和響應值和型別等。

現在我們就以上例中的 get 方法講述如何編寫models 和 controller 。


GET /api/v1.0/designer/paas/{paasid}?field=detail
Request: None

Response:
201
{
    "passid":"xxxxx",
    "local_git":"ssh://localhost/paasdata/confcenter/{paasid}/pdmng/.git"
}
400
{
    "status": "no exist {paasid}"
}

複製程式碼

request: 無

response: 分兩種:成功和失敗,響應值和狀態碼

則:models 層這樣編寫:



201 時的返回值資訊
type PaaSIdInfoResponse struct{
    PaaSid:   string `json:"paasid"`
    LocalGit: string `json:"local_git"`
}


400 時的返回值資訊

type StatusResponse struct{
    Status   string `json:"status"`
}

400 時也可以值定義成返回一個字串資訊。但本文不這麼處理。


定義函式:表示Get 方法觸動的過程


func GetStatusResponse(paasid string) *StatusResponse {
	if paasid == "" {
		return nil
	}
	return &StatusResponse{
		Status: fmt.Sprintf("no exist %s", paasid),
	}
}

func GetSuccessResponse(paasid string) *PaaSIdInfo {
	return &PaaSIdInfo{
		PaaSid:    paasid,
		LocalInfo: fmt.Sprintf("ssh://localhost/paasdata/confcenter/%s/pdmng/.git", paasid),
	}
}

複製程式碼

則 controller 層:

回到 Swagger 上手指南, 我們指出:全文分三個部分,一個是全域性基本資訊:比如Swagger 版本,介紹,BasePath 等; 核心是path 部分:一個是URL 路徑,一個是Parameters 一個是Response .

Beego + Swagger 如何實現這些資訊的呢?

Beego 靠編寫註釋來實現這些資訊:

router.go 檔案資訊註釋來實現全域性資訊:

// @APIVersion 1.0.0
// @Title mobile API
// @Description mobile has every tool to get any job done, so codename for the new mobile APIs.
// @Contact astaxie@gmail.com
package routers



複製程式碼
@APIVersion
@Title
@Description
@Contact
@TermsOfServiceUrl
@License
@LicenseUrl
複製程式碼

填寫關鍵字後面的內容即可改變全域性資訊。

controller 檔案內的註釋來實現path 中的Parameters 和 Response 等

// @Title getStaticBlock
// @Description get all the staticblock by key
// @Param   key     path    string  true        "The email for login"
// @Success 200 {object} models.ZDTCustomer.Customer
// @Failure 400 Invalid email supplied
// @Failure 404 User not found
// @router /staticblock/:key [get]
func (c *CMSController) StaticBlock() {

}

複製程式碼
@Title 表示描述函式資訊
@Description 表示較詳細介紹函式資訊
@Param 表示描述API 動作中的引數:路徑中的引數,傳入的Body等
@Success 表示描述API 正確處理時的返回資訊和狀態碼
@Failure 表示描述API 錯誤處理時的返回值資訊和狀態碼
@router 表示API 路徑URL 
[] 表示該函式的動作型別:post、get、put、delete等
複製程式碼

上例中的controller 這樣寫:


// @Title Get
// @Description get paasid info from API
// @Param paasid path string true "The paasid name"
// @Param field query string true "field"
// @Success 201 {object} models.PaaSIdInfo
// @Failure 400 {object} models.StatusResponse
// @router /paas/:paasid [get]
func (p *PaaSController) Get() {
	paasid := p.Ctx.Input.Param(":paasid")
	if paasid != "" {
		data := models.GetSuccessResponse(paasid)
		p.Data["json"] = data
	} else {
		data := models.GetStatusResponse(paasid)
		p.Data["json"] = data
	}
	p.ServeJSON()
}
複製程式碼

其餘類似:

要是看不懂,正確的做法應該是:

  • 下載Beego
  • 下載Beego 命令列工具 bee
  • 建立API 專案:bee api apitest
  • 首次執行:bee run -gendoc=true -downdoc=true
  • 訪問:http://127.0.0.1:8080/swagger 檢視效果
  • 閱讀:controllers 、models 檔案下的 go 檔案原始碼

總結

本文講述使用Beego + bee + Swagger 實現的API 的編寫。

核心在於理解:

  • beego 架構的MVC 模式
  • Http 請求的關鍵步驟:請求、響應模式
  • 編寫模型層和控制層

最後效果:

Beego+Swagger.png

相關文章