『Beego + Swagger 快速上手』

大纲

  • 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

ChangeLog

  • 2018.02.08 成文
  • 2018.02.07 阅读、编码
  • 2018.02.06 学习 Beego
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • Swashbuckle.AspNetCore Swagger 使用Asp.net core 建立API.生成漂亮的...
    KennethChen93阅读 5,127评论 0 1
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 之前写过一篇使用Beego自动化api文档的文章:Beego自动化文档,随着Beego的更新,1.7.0之后Bee...
    姜家志阅读 8,047评论 0 8
  • 命运最终还是掌握在自己手中,那些所谓能够预言未来的人,只不过是虚张声势罢了。 2017年9月19日 星期二 ...
    雾里的魂阅读 395评论 0 0