使用 Beego 與 Mgo 開發的樣本程式

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

本文為技術翻譯,原文地址(需翻牆):http://www.goinggo.net/2013/12/sample-web-application-using-beego-and.html

簡介

當我發現 beego 架構時感覺非常激動。我只用了大約 4 個小時就將一個現有的 Web 應用程式移植到了該架構上並做了一些端對端測試的調用擴充。我想要與你分享這個基於 beego 的網站。

我構建了一個具有以下功能的樣本 Web 應用程式:

  1. 實現了 2 個通過 mgo 驅動拉取 MongoDB 資料的 Web 調用。
  2. 使用 envconfig 配置環境變數作為參數。
  3. 通過 goconvey 書寫測試案例。
  4. 結合我的 logging 包。

這個樣本的代碼可以在 GoingGo 帳戶下的 GitHub 倉庫中找到:https://github.com/goinggo/beego-mgo。

你可以拉取並運行它。它使用了我在 MongoLab 建立的公開 MongoDB 資料庫。你會需要安裝 git 和 bazaar 以保證能夠使用 go get 來將它安裝到你系統中。

go get github.com/goinggo/beego-mgo

使用 zscripts 檔案夾裡的腳步可以快速運行或測試 Web 應用程式。

Web 應用程式代碼結構

讓我們來看一下項目結構和不同檔案夾的功能:

  • app:包含 business、model 和 service 層。
  • app/models:用於 business 和 service 層的資料結構。
  • app/services:用於為不同服務提供基本函數。可以是針對資料庫或 Web 調用的函數。
  • app/business:被 controller 和處理 business 規則的函數所調用。多種服務的組合調用可用於實現更大層面上的功能。
  • controllers:URL 或 Web API 呼叫的切入點。控制器會直接調用 business 層的函數來直接處理請求。
  • routes:用於 URL 和控制器代碼的映射。
  • static:用於存放指令碼、CSS 和圖片等靜態資源。
  • test:可使用 go test 啟動並執行測試案例。
  • utilities:用於支援 Web 應用程式的代碼。資料庫操作和 panic 處理的範例與抽象化代碼。
  • views:用於存放模板檔案。
  • zscripts:協助更方便構建、運行和測試 Web 應用程式的指令碼。

控制器、模型和服務

這些層的程式碼群組成了 Web 應用程式。我的架構背後的理念是儘可能的抽象化代碼為樣板。這就要求我實現一個 base 控制器包和 base 服務包。

base 控制器包

base 控制器包由所有控制器所要求的預設抽象的控制器行為來組成:

type (    BaseController struct {        beego.Controller        services.Service    })func (this *BaseController) Prepare() {    this.UserId = "unknown"    tracelog.TRACE(this.UserId, "Before",        "UserId[%s] Path[%s]", this.UserId, this.Ctx.Request.URL.Path)    var err error    this.MongoSession, err = mongo.CopyMonotonicSession(this.UserId)    if err != nil {        tracelog.ERRORf(err, this.UserId, "Before", this.Ctx.Request.URL.Path)        this.ServeError(err)    }}func (this *BaseController) Finish() {    defer func() {        if this.MongoSession != nil {            mongo.CloseSession(this.UserId, this.MongoSession)            this.MongoSession = nil        }    }()    tracelog.COMPLETEDf(this.UserId, "Finish", this.Ctx.Request.URL.Path)}

一個名為 BaseController 的新類型直接由類型 beego.Controllerservices.Service 嵌入而組成。這樣做就可以直接獲得這兩個類型的所有欄位和方法給 BaseController,並直接操作這些欄位和方法。

服務包

服務包用於樣板化所有服務所要求的代碼:

type (    Service struct {        MongoSession *mgo.Session        UserId string    })func (this *Service) DBAction(databaseName string, collectionName string,                              mongoCall mongo.MongoCall) (err error) {    return mongo.Execute(this.UserId, this.MongoSession,                         databaseName, collectionName, mongoCall)}

Service 類型中,包含了 Mongo 會話和使用者識別碼。函數 DBAction 提供了運行 MongoDB 命令和查詢的抽象層。

實現一個 Web 調用

基於 base 類型和樣板函數,我們現在可以實現一個 Web 調用了:

Buoy Controller

類型 BuoyController 實現了兩個結合 BaseController 和 business 層 Web API 呼叫。我們主要關注名為 Station 的 Web 調用。

type BuoyController struct {    bc.BaseController}func (this *BuoyController) Station() {    buoyBusiness.Station(&this.BaseController, this.GetString(":stationId"))}

類型 BuoyController 直接由單獨的 BaseController 組成。通過這種組合方式,BuoyController 自動獲得了已經自訂實現的 PrepareFinish 方法以及所有 beego.Controller 的欄位。

函數 Station 通過下面路由分發。stationId 作為 URL 的最後一項。當這個路由被請求時,一個 BuoyController 對象會被執行個體化並執行函數 Station

beego.Router("/station/:stationId", &controllers.BuoyController{}, "get:Station")

函數 Station 會在底層調用 business 層的代碼來處理請求。

Buoy Business

Buoy Business 包實現了 BuoyController 的 business 層。讓我看看在 BuoyController 中的函數 Station 所調用的 business 層的代碼是怎樣的:

func Station(controller *bc.BaseController, stationId string) {    defer bc.CatchPanic(controller, "Station")    tracelog.STARTEDf(controller.UserId, "Station", "StationId[%s]", stationId)    buoyStation, err := buoyService.FindStation(&controller.Service, stationId)    if err != nil {        ServeError(err)        return    }    controller.Data["json"] = &buoyStation    controller.ServeJson()    tracelog.COMPLETED(controller.UserId, "Station")}

你可以看到 business 層的函數 Station 處理了整個請求的邏輯。這個函數還使用了Buoy Service 來處理與 MongoDB 的互動。

Buoy Service

Buoy Service 包實現了與 MongoDB 的互動。讓我們來看下被 business 層的函數 Station 所調用的函數 FindStation 的代碼:

func FindStation(service *services.Service, stationId string) (buoyStation *buoyModels.BuoyStation, err error) {    defer helper.CatchPanic(&err, service.UserId, "FindStation")    tracelog.STARTED(service.UserId, "FindStation")    queryMap := bson.M{"station_id": stationId}    tracelog.TRACE(service.UserId, "FindStation",        "Query : %s", mongo.ToString(queryMap))    buoyStation = &buoyModels.BuoyStation{}    err = service.DBAction(Config.Database, "buoy_stations",        func(collection *mgo.Collection) error {            return collection.Find(queryMap).One(buoyStation)        })    if err != nil {        tracelog.COMPLETED_ERROR(err, service.UserId, "FindStation")        return buoyStation, err    }    tracelog.COMPLETED(service.UserId, "FindStation")    return buoyStation, err}

函數 FindStation 用於準備通過 DBAction 函數進行與 MongoDB 的查詢與執行操作。

端到端測試

我們現在有一個 URL 可以路由到一個控制器以及相應的 business 與 service 層的邏輯,它可以通過以下方式測試:

func TestStation(t *testing.T) {    r, _ := http.NewRequest("GET", "/station/42002", nil)    w := httptest.NewRecorder()    beego.BeeApp.Handlers.ServeHTTP(w, r)    err := struct {        Error string    }{}    json.Unmarshal(w.Body.Bytes(), &err)    Convey("Subject: Test Station Endpoint\n", t, func() {        Convey("Status Code Should Be 200", func() {            So(w.Code, ShouldEqual, 200)        })        Convey("The Result Should Not Be Empty", func() {            So(w.Body.Len(), ShouldBeGreaterThan, 0)        })        Convey("The Should Be No Error In The Result", func() {            So(len(err.Error), ShouldEqual, 0)        })    })}

測試建立了一個某個路由的虛擬調用。這種做法很贊,因為我們不需要真正地去啟動一個 Web 應用程式來測試代碼。使用 goconvey 我們能夠建立非常優雅的輸出且易於閱讀。

以下是一個測試失敗的範例:

Subject: Test Station Endpoint  Status Code Should Be 200 ✘  The Result Should Not Be Empty   The Should Be No Error In The Result ✘Failures:* /Users/bill/Spaces/Go/Projects/src/github.com/goinggo/beego-mgo/test/endpoints/buoyEndpoints_test.go Line 35:Expected: '200'Actual: '400'(Should be equal)* /Users/bill/Spaces/Go/Projects/src/github.com/goinggo/beego-mgo/test/endpoints/buoyEndpoints_test.go Line 37:Expected: '0'Actual: '9'(Should be equal)3 assertions thus far--- FAIL: TestStation-8 (0.03 seconds)

以下是一個測試成功的範例:

Subject: Test Station Endpoint  Status Code Should Be 200   The Result Should Not Be Empty   The Should Be No Error In The Result 3 assertions thus far--- PASS: TestStation-8 (0.05 seconds)

結論

花點時間下載這個項目隨便看看。我盡最大努力讓你能夠清晰地看到我所想要展示給你的重點。beego 架構讓你能夠非常輕鬆地實現抽象和樣板代碼,遵照 go 的風格整合 go 測試、運行及部署。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.