日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

beego API开发以及自动化文档

發(fā)布時(shí)間:2025/3/17 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 beego API开发以及自动化文档 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

beego API開發(fā)以及自動化文檔

beego1.3版本已經(jīng)在上個(gè)星期發(fā)布了,但是還是有很多人不了解如何來進(jìn)行開發(fā),也是在一步一步的測試中開發(fā),期間QQ群里面很多人都問我如何開發(fā),我的業(yè)余時(shí)間實(shí)在是排的太滿了,實(shí)在是沒辦法一一回復(fù)大家,在這里和大家說聲對不起,這兩天我又不斷的改進(jìn),寫了一個(gè)應(yīng)用示例展示如何使用beego開發(fā)API已經(jīng)自動化文檔和測試,這里就和大家詳細(xì)的解說一下。

自動化文檔開發(fā)的初衷

我們需要開發(fā)一個(gè)API應(yīng)用,然后需要和手機(jī)組的開發(fā)人員一起合作,當(dāng)然我們首先想到的是文檔先行,我們也根據(jù)之前的經(jīng)驗(yàn)寫了我們需要的API原型文檔,我們還是根據(jù)github的文檔格式寫了一些漂亮的文檔,但是我們開始擔(dān)心這個(gè)文檔如果兩邊不同步怎么辦?因?yàn)楫吘故窃臀臋n,變動是必不可少的。手機(jī)組有一個(gè)同事之前在雅虎工作過,他推薦我看一個(gè)swagger的應(yīng)用,看了swagger的標(biāo)準(zhǔn)和文檔化的要求,感覺太棒了,這個(gè)簡直就是神器啊,通過swagger可以方便的查看API的文檔,同時(shí)使用API的用戶可以直接通過swagger進(jìn)行請求和獲取結(jié)果。所以我就開始學(xué)習(xí)swagger的標(biāo)準(zhǔn),同時(shí)開始進(jìn)行Go源碼的研究,通過Go里面的AST進(jìn)行源碼分析,針對comments解析,然后生成swagger標(biāo)準(zhǔn)的json格式,這樣最后就可以和swagger完美結(jié)合了。

這樣做的好處有三個(gè):

  • 注釋標(biāo)準(zhǔn)化

  • 有了注釋之后,以后API代碼維護(hù)相當(dāng)方便

  • 根據(jù)注釋自動化生成文檔,方便調(diào)用的用戶查看和測試

  • beego API應(yīng)用入門

    請大家更新到最新的bee和beego

    go?get?-u?github.com/beego/bee go?get?-u?github.com/astaxie/beego

    然后進(jìn)入到你的GOPATH/src目錄,執(zhí)行命令bee api bapi,進(jìn)入目錄cd bapi,執(zhí)行命令bee run -downdoc=true -docgen=true.請看下面我執(zhí)行的效果圖:

    執(zhí)行完成之后就打開瀏覽器,輸入U(xiǎn)RL:http://127.0.0.1:8080/swagger/swagger-1/

    記住這里必須要用127.0.0.1,不能使用localhost,存在CORS問題,Ajax跨域

    我們的效果和應(yīng)用都出來了,很酷很炫吧,那這后面到底采用了怎么樣的一些技術(shù)呢?讓我們一步一步來講解這些細(xì)節(jié):

    項(xiàng)目目錄

    我們首先來了解一下bee api創(chuàng)建的應(yīng)用的目錄結(jié)構(gòu):

    |--?bapi |--?conf |???`--?app.conf |--?controllers |???|--?object.go |???`--?user.go |--?docs |???|--?doc.go |???`--?docs.go |--?lastupdate.tmp |--?main.go |--?models |???|--?object.go |???`--?user.go |--?routers |???|--?commentsRouter.go |???`--?router.go |--?swagger `--?tests`--?default_test.go
    • main.go 是程序的統(tǒng)一入口文件

    • bapi 是生成的二進(jìn)制文件

    • conf 配置文件目錄,app.conf

    • controllers 控制器目錄,主要是邏輯的處理

    • models 是數(shù)據(jù)處理層的目錄

    • docs 是自動化生成文檔的目錄

    • lastupdate.tmp 是一個(gè)注解路由的緩存文件

    • routers是路由目錄,主要涉及一些路由規(guī)則

    • swagger 是一個(gè)html靜態(tài)資源目錄,是通過bee自動下載的,主要就是展示我們看到的界面及測試

    • test 目錄是針對應(yīng)用的測試用例,beego相比其他revel框架的好處之一就是無需啟動應(yīng)用就可以執(zhí)行test case。

    入口文件main

    我們第一步先來看一下入口是怎么寫的?

    package?mainimport?(_?"bapi/docs"_?"bapi/routers""github.com/astaxie/beego" )func?main()?{if?beego.RunMode?==?"dev"?{beego.DirectoryIndex?=?truebeego.StaticDir["/swagger"]?=?"swagger"}beego.Run() }

    入口文件就是一個(gè)普通的beego應(yīng)用的標(biāo)準(zhǔn)代碼,只是這里多了幾行代碼,把swagger加入了static,因?yàn)槲覀冃枰盐臋n服務(wù)器集成到beego的API應(yīng)用中來。然后增加了docs的初始化引入,和router的效果一樣。接下里我們先來看看自動化API的路由是怎么設(shè)計(jì)的

    namespace路由

    自動化路由才有了namespace來進(jìn)行設(shè)計(jì),而且注意兩點(diǎn),第一目前只支持namespace的路由支持自動化文檔,第二只支持NSNamespace和NSInclude解析,而且是只能兩個(gè)層級,先看我們的路由設(shè)置:

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

    我們先來看一下這個(gè)代碼,首先是使用beego.NewNamespace創(chuàng)建一個(gè)ns的變量,這個(gè)變量里面其實(shí)就是存儲了一棵路由樹,我們可以把這棵樹加到其他任意已經(jīng)存在的樹中去,這也就是namespace的好處,可以在任意的模塊中設(shè)計(jì)自己的namespace,然后把這個(gè)namespace加到其他的應(yīng)用中去,可以增加任意的前綴等。

    這里我們分析一下NewNamespace這個(gè)函數(shù),這個(gè)函數(shù)的定義是這樣的NewNamespace(prefix string, params ...innnerNamespace) *Namespace,他的第一個(gè)參數(shù)就是前綴,第二個(gè)參數(shù)是innnerNamespace多參數(shù),那么我們來看看innnerNamespace的定義是什么:

    type?innnerNamespace?func(*Namespace)

    它是一個(gè)函數(shù),也就是只要是符合參數(shù)是*Namespace的函數(shù)都可以。那么在beego里面定義了如下的方法支持返回這個(gè)函數(shù)類型:

    • NSCond(cond namespaceCond) innnerNamespace

    • NSBefore(filiterList ...FilterFunc) innnerNamespace

    • NSAfter(filiterList ...FilterFunc) innnerNamespace

    • NSInclude(cList …ControllerInterface) innnerNamespace

    • NSRouter(rootpath string, c ControllerInterface, mappingMethods …string) innnerNamespace

    • NSGet(rootpath string, f FilterFunc) innnerNamespace

    • NSPost(rootpath string, f FilterFunc) innnerNamespace

    • NSDelete(rootpath string, f FilterFunc) innnerNamespace

    • NSPut(rootpath string, f FilterFunc) innnerNamespace

    • NSHead(rootpath string, f FilterFunc) innnerNamespace

    • NSOptions(rootpath string, f FilterFunc) innnerNamespace

    • NSPatch(rootpath string, f FilterFunc) innnerNamespace

    • NSAny(rootpath string, f FilterFunc) innnerNamespace

    • NSHandler(rootpath string, h http.Handler) innnerNamespace

    • NSAutoRouter(c ControllerInterface) innnerNamespace

    • NSAutoPrefix(prefix string, c ControllerInterface) innnerNamespace

    • NSNamespace(prefix string, params …innnerNamespace) innnerNamespace

    因此我們可以在NewNamespace這個(gè)函數(shù)的第二個(gè)參數(shù)列表中使用上面的任意函數(shù)作為參數(shù)調(diào)用。

    我們看一下路由代碼,這是一個(gè)層級嵌套的函數(shù),第一個(gè)參數(shù)是/v1,即為/v1開頭的路由樹,第二個(gè)參數(shù)是beego.NSNamespace,第三個(gè)參數(shù)也是beego.NSNamespace,也就是路由樹嵌套了路由樹,而我們的beego.NSNamespace里面也是和NewNamespace一樣的參數(shù),第一個(gè)參數(shù)是路由前綴,第二個(gè)參數(shù)是slice參數(shù)。這里我們調(diào)用了beego.NSInclude來進(jìn)行注解路由的引入,這個(gè)函數(shù)是專門為注解路由設(shè)計(jì)的,我們可以看到這個(gè)設(shè)計(jì)里面我們沒有任何的路由信息,只是設(shè)置了前綴,那么這個(gè)的路由是在哪里設(shè)置的呢?我們接下來分析什么是注解路由。

    注解路由

    可能有些同學(xué)不了解什么是注解路由,也就是在Controller類上添加一個(gè)注釋讓框架給自動添加Route,那么我們來看一下ObjectController和UserController中怎么寫路由注解的:

    //?Operations?about?object type?ObjectController?struct?{beego.Controller }//?@Title?create //?@Description?create?object //?@Param???body????????body????models.Object???true????????"The?object?content" //?@Success?200?{string}?models.Object.Id //?@Failure?403?body?is?empty //?@router?/?[post] func?(this?*ObjectController)?Post()?{var?ob?models.Objectjson.Unmarshal(this.Ctx.Input.RequestBody,?&ob)objectid?:=?models.AddOne(ob)this.Data["json"]?=?map[string]string{"ObjectId":?objectid}this.ServeJson() }

    我們看到我們的每一個(gè)函數(shù)上面有大段的注釋,注解路由其實(shí)主要關(guān)注最后一行// @router / [post],這一行的注釋就是表示這個(gè)函數(shù)是注冊到路由/,支持方法是post。

    和我們平常的時(shí)候使用beego.Router("/", &ObjectController{},"post:Post")的效果是一模一樣的,只是這一次框架幫你自動注冊了這樣的路由,框架是如何來自動注冊的呢?在應(yīng)用啟動的時(shí)候,會判斷是否有調(diào)用NSInclude,在調(diào)用的時(shí)候,判斷RunMode是否是dev模式,是的話就會判斷是否之前有分析過,并且分析對象目錄有更新,就使用Go的AST進(jìn)行源碼分析(當(dāng)然只分析NSInclude調(diào)用的controller),然后生成文件routers/commentsRouter.go,在該文件中會自動注冊我們需要的路由信息。這樣就完成了整個(gè)的注解路由注冊。

    注解路由是使用// @router 開頭來申明的,而且必須放在你要注冊的函數(shù)的上方,和其他注釋@Title @Description的順序無關(guān),你可以放在第一行,也可以最后一行。有兩個(gè)參數(shù),第一個(gè)是需要注冊的路由,第二個(gè)是支持的方法。

    路由可以支持beego支持的任意規(guī)則,例如/object/:key這樣的參數(shù)路由,也可以固定路由/object,也可以是正則路由/cms_:id([0-9]+).html

    支持的HTTP方法必須使用[]中間是支持的方法列表,多個(gè)使用,分割,例如[post,get]。但是目前自動化文檔只支持一個(gè)方法,也就是你多個(gè)的方法的時(shí)候無法做到RESTFul到同一個(gè)函數(shù),也不鼓勵你這樣設(shè)計(jì)的API。如果你API設(shè)計(jì)的時(shí)候支持了多個(gè)方法,那么文檔生成的時(shí)候默認(rèn)是取第一個(gè)作為支持的方法。

    上面我們看到我們的方法上面有很多注釋,那么接下來就進(jìn)入我們今天的重點(diǎn):自動化文檔

    自動化文檔

    所謂的自動化文檔,說白了就是根據(jù)我們的注釋自動的生成我們可以看得懂的漂亮文檔。我們上面也說了寫注釋不僅僅是方便我們的代碼維護(hù),邏輯闡述,同時(shí)如果能夠自動生成文檔,那么對于使用API的用戶來說也是很大的幫助。那么如何進(jìn)行自動化文檔生成呢?

    我當(dāng)初看了swagger的展示效果之后,首先研究了他的spec,發(fā)現(xiàn)是一些json數(shù)據(jù),只要我們的API能夠生成swagger認(rèn)識的json就可以了,因此我的思路就來了,根據(jù)注釋生成swagger的JSON標(biāo)準(zhǔn)數(shù)據(jù)輸出。swagger提供了一個(gè)例子代碼:petstore?我就是根據(jù)這個(gè)例子的格式一步一步實(shí)現(xiàn)了現(xiàn)在的自動化文檔。

    首先第一步就是API的描述:

    API文檔

    我們看到在router.go里面頭部有一大段的注釋,這些注釋就是描述整個(gè)項(xiàng)目的一些信息:

    //?@APIVersion?1.0.0 //?@Title?beego?Test?API //?@Description?beego?has?a?very?cool?tools?to?autogenerate?documents?for?your?API //?@Contact?astaxie@gmail.com //?@TermsOfServiceUrl?http://beego.me/ //?@License?Apache?2.0 //?@LicenseUrl?http://www.apache.org/licenses/LICENSE-2.0.html

    這里面主要是幾個(gè)標(biāo)志:

    • @APIVersion

    • @Title

    • @Description

    • @Contact

    • @TermsOfServiceUrl

    • @License

    • @LicenseUrl

    這里每一個(gè)都不是必須的,你可以寫也可以不寫,后面就是一個(gè)字符串,你可以使用任意喜歡的字符進(jìn)行描述。我們來看一下生成的:http://127.0.0.1:8080/docs

    {"apiVersion":?"1.0.0","swaggerVersion":?"1.2","apis":?[{"path":?"/object","description":?"Operations?about?object\n"},{"path":?"/user","description":?"Operations?about?Users\n"}],"info":?{"title":?"beego?Test?API","description":?"beego?has?a?very?cool?tools?to?autogenerate?documents?for?your?API","contact":?"astaxie@gmail.com","termsOfServiceUrl":?"http://beego.me/","license":?"Url?http://www.apache.org/licenses/LICENSE-2.0.html"} }

    這是首次請求的一些信息,那么apis是怎么來的呢?這個(gè)就是根據(jù)你的namespace進(jìn)行源碼AST分析獲取的,所以目前只支持兩層的namespace嵌套,而且必須是兩層,第一層是baseurl,第二層就是嵌套的namespace的prefix。也就是上面的path信息,那么里面的description那里獲取的呢?請看控制器的注釋,

    控制器注釋文檔

    針對每一個(gè)控制我們可以增加注釋,用來描述該控制器的作用:

    //?Operations?about?object type?ObjectController?struct?{beego.Controller }

    這個(gè)注釋就是用來表示我們的每一個(gè)控制器API的作用,而控制器的函數(shù)里面的注釋就是用來表示調(diào)用的路由、參數(shù)、作用以及返回的信息。

    //?@Title?Get //?@Description?find?object?by?objectid //?@Param???objectId????????path????string??true????????"the?objectid?you?want?to?get" //?@Success?200?{object}?models.Object //?@Failure?403?:objectId?is?empty //?@router?/:objectId?[get] func?(this?*ObjectController)?Get()?{ }

    從上面的注釋我們可以把我們的注釋分為以下類別:

    • @Title

      接口的標(biāo)題,用來標(biāo)示唯一性,唯一,可選

      格式:之后跟一個(gè)描述字符串

    • @Description

      接口的作用,用來描述接口的用途,唯一,可選

      格式:之后跟一個(gè)描述字符串

    • @Param

      請求的參數(shù),用來描述接受的參數(shù),多個(gè),可選

      格式:變量名 傳輸類型 類型 是否必須 描述

      傳輸類型:

      類型:

      變量名和描述是一個(gè)字符串

      是否必須:true 或者false

      • string

      • int

      • int64

      • 對象,這個(gè)地方大家寫的時(shí)候需要注意,需要是相對于當(dāng)前項(xiàng)目的路徑.對象,例如models.Object表示models目錄下的Object對象,這樣bee在生成文檔的時(shí)候會去掃描改對象并顯示給用戶改對象。

      • query 表示帶在url串里面?aa=bb&cc=dd

      • form 表示使用表單遞交數(shù)據(jù)

      • path 表示URL串中得字符,例如/user/{uid} 那么uid就是一個(gè)path類型的參數(shù)

      • body 表示使用raw body進(jìn)行數(shù)據(jù)的傳輸

      • header 表示通過header進(jìn)行數(shù)據(jù)的傳輸

    • @Success

      成功返回的code和對象或者信息

      格式:code 對象類型 信息或者對象路徑

      code:表示HTTP的標(biāo)準(zhǔn)status code,200 201等

      對象類型:{object}表示對象,其他默認(rèn)都認(rèn)為是字符類型,會顯示第三個(gè)參數(shù)給用戶,如果是{object}類型,那么就會去掃描改對象,并顯示給用戶

      對象路徑和上面Param中得對象類型一樣,使用路徑.對象的方式來描述

    • @Failure

      錯誤返回的信息,

      格式: code 信息

      code:同上Success

      錯誤信息:字符串描述信息

    • @router

      上面已經(jīng)描述過支持兩個(gè)參數(shù),第一個(gè)是路由,第二個(gè)表示支持的HTTP方法

    那么我們通過上面的注釋會生成怎么樣的JSON信息呢?

    {"path":?"/object/{objectId}","description":?"","operations":?[{"httpMethod":?"GET","nickname":?"Get","type":?"","summary":?"find?object?by?objectid","parameters":?[{"paramType":?"path","name":?"objectId","description":?"\"the?objectid?you?want?to?get\"","dataType":?"string","type":?"","format":?"","allowMultiple":?false,"required":?true,"minimum":?0,"maximum":?0}],"responseMessages":?[{"code":?200,"message":?"models.Object","responseModel":?"Object"},{"code":?403,"message":?":objectId?is?empty","responseModel":?""}]}] }

    上面闡述的這些描述都是可以使用一個(gè)或者多個(gè)?'\t', '\n', '\v', '\f', '\r', ' ', U+0085 (NEL), U+00A0 (NBSP)進(jìn)行分割

    對象自定義注釋

    我們的對象定義如下:

    type?Object?struct?{ObjectId???stringScore??????int64PlayerName?string }

    通過掃描生成的代碼如下:

    Object?{ ObjectId?(string,?optional):?, PlayerName?(string,?optional):?, Score?(int64,?optional): }

    我們發(fā)現(xiàn)字段都是optional的,而且沒有任何針對字段的描述,其實(shí)我們可以在對象定義里面增加如下的tag:

    type?Object?struct?{ObjectId???string???`required:"true"?description:"object?id"`Score??????int64????????`required:"true"?description:"players's?scores"`PlayerName?string???`required:"true"?description:"plaers?name,?used?in?system"` }

    而且如果你的對象tag里面如果存在json或者thrift描述,那么就會使用改描述作為字段名,即如下的代碼:

    type?Object?struct?{ObjectId???string???`json:"object_id"`Score??????int64????????`json:"player_score"`PlayerName?string???`json:"player_name"` }

    就會輸出如下的文檔信息:

    Object?{ object_id?(string,?optional):?, player_score?(string,?optional):?, player_name?(int64,?optional): }

    常見錯誤及問題

  • Q:bee沒有上面執(zhí)行的命令?

    A:請更新bee到最新版本,目前bee的版本是1.1.2,beego的版本是1.3.1

  • Q:bee更新的時(shí)候出錯了?

    A:第一可能是GFW的問題,第二可能是你修改過了源碼,刪除重新下載,第三可能你升級了Go版本,你需要刪除GOPATH/pkg下的所有文件

  • Q:下載swagger很慢?

    A:想辦法讓他變快,因?yàn)槲椰F(xiàn)在放在了github上面

  • Q:文檔生成了,但是我沒辦法測試請求?

    A:你看看你訪問的地址是不是和請求的URL是同一個(gè)地址,因?yàn)閟wagger是使用Ajax請求數(shù)據(jù)的,所以跨域的問題,解決CORS的辦法就是保持域一致,包括URL和端口。

  • Q:運(yùn)行的時(shí)候發(fā)生了未知的錯誤?

    A:那就來提issue或者給我留言吧,我會盡力幫助你解決你遇到的問題


  • 轉(zhuǎn)載于:https://my.oschina.net/astaxie/blog/284072

    總結(jié)

    以上是生活随笔為你收集整理的beego API开发以及自动化文档的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。