用beego開發服務端應用


用beego開發服務端應用

  • 說明
  • Quick Start
  • 開發文檔
  • 目錄結構說明
  • 使用配置文件
  • beego默認參數
  • 路由設置
  • 需要特別注意的NSAfter()
  • 使用數據庫
  • 數據庫遷移(migration)
  • beego.Controller處理http請求
  • 參考
  • 說明

    beego是國內團隊開源的golang開發框架,是一個關注度和使用量都比價高的項目。

    Quick Start

    beego快速入門中給出一個很簡單的例子。

    安裝

    首先需要安裝beego和bee工具:

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

    為了能夠直接使用bee命令,需要將$GOPATH/bin添加到$PATH變量中。

    創建應用

    創建一個名為hello的應用,可以選擇web應用,或者api應用:

    $ bee new hello     //創建一個web應用
    $ bee api hello     //創建一個api應用
    

    執行結束后,會在當前目錄下創建名為hello的目錄:

    .
    |____hello
    | |____conf
    | | |____app.conf
    | |____controllers
    | | |____default.go
    | |____main.go
    | |____models
    | |____routers
    | | |____router.go
    | |____static
    | | |____css
    | | |____img
    | | |____js
    | | | |____reload.min.js
    | |____tests
    | | |____default_test.go
    | |____views
    | | |____index.tpl
    

    編譯運行

    進入hello目錄中,執行bee run,就會完成編譯、運行:

    $ cd hello/
    $ bee run
    ______
    | ___ \
    | |_/ /  ___   ___
    | ___ \ / _ \ / _ \
    | |_/ /|  __/|  __/
    \____/  \___| \___| v1.9.1
    2017/10/23 14:33:05 INFO     ▶ 0001 Using 'hello' as 'appname'
    2017/10/23 14:33:05 INFO     ▶ 0002 Initializing watcher...
    2017/10/23 14:33:06 SUCCESS  ▶ 0003 Built Successfully!
    2017/10/23 14:33:06 INFO     ▶ 0004 Restarting 'hello'...
    2017/10/23 14:33:06 SUCCESS  ▶ 0005 './hello' is running...
    2017/10/23 14:33:06 [I] [asm_amd64.s:2197] http server Running on http://:8080
    

    打包發布

    項目打包發布:

    $ bee pack
    

    代碼生成

    生成models:

    bee generate model user -fields="name:string,age:int"
    

    生成controller:

    bee generate controller user
    

    生成view:

    bee generate view user
    

    生成文檔:

    bee generate docs
    

    開發文檔

    beego開發文檔中對beego做了很詳細的說明。

    beego執行邏輯

    目錄結構說明

    .
    |____hello
    | |____conf           <- 配置文件
    | | |____app.conf
    | |____controllers    <- 控制器,即http請求的handler
    | | |____default.go
    | |____main.go        <- main函數
    | |____models
    | |____routers        <- 路由,將url關聯到controllers
    | | |____router.go
    | |____static         <- 靜態文件
    | | |____css
    | | |____img
    | | |____js
    | | | |____reload.min.js
    | |____tests          <- 測試
    | | |____default_test.go
    | |____views          <- 頁面模版,controller中可以直接渲染對應的tpl文件
    | | |____index.tpl
    

    使用配置文件

    beego參數配置中講解如何使用配置文件、如何配置參數。

    beego默認解析應用目錄下的conf/app.conf文件,配置項可以通過beego.AppConfig.*讀取:

    beego.AppConfig.String("mysqluser")
    

    beego.Appconfig包含多個方法:

    Set(key, val string) error
    String(key string) string
    Strings(key string) []string
    Int(key string) (int, error)
    Int64(key string) (int64, error)
    Bool(key string) (bool, error)
    Float(key string) (float64, error)
    DefaultString(key string, defaultVal string) string
    DefaultStrings(key string, defaultVal []string)
    DefaultInt(key string, defaultVal int) int
    DefaultInt64(key string, defaultVal int64) int64
    DefaultBool(key string, defaultVal bool) bool
    DefaultFloat(key string, defaultVal float64) float64
    DIY(key string) (interface{}, error)
    GetSection(section string) (map[string]string, error)
    SaveConfigFile(filename string) error
    

    配置文件中可以配置section,通過runmode指定要使用的section,例如:

    appname = beepkg
    httpaddr = "127.0.0.1"
    httpport = 9090
    runmode ="dev"
    autorender = false
    recoverpanic = false
    viewspath = "myview"
    
    [dev]
    httpport = 8080
    [prod]
    httpport = 8088
    [test]
    httpport = 8888
    

    對於section的配置項,通過下面的方式讀取,模式::配置參數名:

    beego.AppConfig.String(“dev::mysqluser”)
    

    配置文件中可以使用環境變量:

    runmode  = "${ProRunMode||dev}"
    httpport = "${ProPort||9090}"
    

    加載特定的配置文件,可以加載多個配置文件,key不能沖突:

    beego.LoadAppConfig("ini", "conf/app2.conf")
    beego.LoadAppConfig("ini", "conf/app3.conf")
    

    beego默認參數

    beego的默認參數全部保存在beego.BConfig中。,可以訪問、修改所有的配置信息。

    在配置文件中設置的同名的key(不區分大小寫)的值會覆蓋默認值,例如:

    appname = hello
    httpport = 8080
    runmode = dev
    
    [dev]
    AutoRender=false    #會覆蓋beego.BConfig.WebConfig.AutoRender的默認值
    
    [test]
    
    [prod]
    

    App配置:

    beego.BConfig.AppName = "beego"
    beego.BConfig.RunMode = "dev"
    beego.BConfig.RouterCaseSensitive = true
    beego.BConfig.ServerName = "beego"
    beego.BConfig.RecoverPanic = true
    beego.BConfig.EnableGzip = false
    beego.BConfig.MaxMemory = 1 << 26
    beego.BConfig.EnableErrorsShow = true
    beego.BConfig.EnableErrorsRender = true
    

    Web配置:

    beego.BConfig.WebConfig.AutoRender = true
    beego.BConfig.WebConfig.EnableDocs = true
    beego.BConfig.WebConfig.FlashName = "BEEGO_FLASH"
    beego.BConfig.WebConfig.FlashSeperator = "BEEGOFLASH"
    beego.BConfig.WebConfig.DirectoryIndex = false
    beego.BConfig.StaticDir = static
    beego.BConfig.WebConfig.StaticExtensionsToGzip = []string{".css", ".js"}
    beego.BConfig.WebConfig.TemplateLeft="
    beego.BConfig.WebConfig.TemplateRight="
    beego.BConfig.WebConfig.ViewsPath="views"
    beego.BConfig.WebConfig.EnableXSRF = false
    beego.BConfig.WebConfig.XSRFKEY = "beegoxsrf"
    beego.BConfig.WebConfig.XSRFExpire = 0
    

    監聽配置:

    beego.BConfig.Listen.Graceful=false
    beego.BConfig.Listen.ServerTimeOut=0
    beego.BConfig.Listen.ListenTCP4 = "tcp4"
    beego.BConfig.Listen.EnableHTTP = true
    beego.BConfig.Listen.HTTPAddr = ""
    beego.BConfig.Listen.HTTPPort = 8080
    beego.BConfig.Listen.EnableHTTPS = false
    beego.BConfig.Listen.HTTPSAddr = ""
    beego.BConfig.Listen.HTTPSPort = 10443
    beego.BConfig.Listen.HTTPSCertFile = "conf/ssl.crt"
    beego.BConfig.Listen.HTTPSKeyFile = "conf/ssl.key"
    beego.BConfig.Listen.EnableAdmin = false
    beego.BConfig.Listen.AdminAddr = "localhost"
    beego.BConfig.Listen.AdminPort = 8088
    beego.BConfig.Listen.EnableFcgi = false
    beego.BConfig.Listen.EnableStdIo = false
    

    Session配置:

    beego.BConfig.WebConfig.Session.SessionOn = false
    beego.BConfig.WebConfig.Session.SessionProvider = ""
    beego.BConfig.WebConfig.Session.SessionName = "beegosessionID"
    beego.BConfig.WebConfig.Session.SessionGCMaxLifetime = 3600
    beego.BConfig.WebConfig.SessionProviderConfig
    beego.BConfig.WebConfig.Session.SessionCookieLifeTime = 3600
    beego.BConfig.WebConfig.Session.SessionAutoSetCookie = true
    beego.BConfig.WebConfig.Session.SessionDomain = ""
    

    Log配置:

    beego.BConfig.Log.AccessLogs = false
    beego.BConfig.Log.FileLineNum = true
    beego.BConfig.Log.Outputs = map[string]string{"console": ""}
    

    路由設置

    beego支持三種路由: 基礎路由、正則路由、自動路由。

    路由的表述方式

    支持用正則的方式書寫路由,參考了sinatra的路由實現。

     路由規則                           可以匹配
    /api/?:id                ---->  /api/, /api/123 id=123
    /api/:id                 ---->  /api/123  id=123
    /api/:id([0-9]+)         ---->  /api/123  id=123
    /user/:username([\w]+)   ---->  /user/abc username=abc
    /download/*.*            ---->  /download/file/api.xml  path=file/api ext=xml
    /download/ceshi/*        ---->  /download/cechis/file/api.json  splat=file/api.json
    /:id:int                 ---->  等同於/:id([0-9]+)
    /:hi:string              ---->  等同於/:hi([\w]+)
    /cms_:id([0-9]+).html    ---->  /cms_123.html  id=123
    

    可以通過*context.Context的Input.Param()方法讀取路由中的變量:

    ctx.Input.Param(":id")
    

    在Controller中,通過下面的方式獲取路由中的變量,this是controller:

    this.Ctx.Input.Param(":id")
    this.Ctx.Input.Param(":username")
    this.Ctx.Input.Param(":splat")
    this.Ctx.Input.Param(":path")
    this.Ctx.Input.Param(":ext")
    

    直接設置路由

    routers/router.go中設置,可以使用下面的基礎函數直接設置路由:

    beego.Get(router, beego.FilterFunc)
    beego.Post(router, beego.FilterFunc)
    beego.Put(router, beego.FilterFunc)
    beego.Head(router, beego.FilterFunc)
    beego.Options(router, beego.FilterFunc)
    beego.Delete(router, beego.FilterFunc)
    beego.Any(router, beego.FilterFunc)
    

    例如:

    //響應post /alice
    beego.Post("/alice",func(ctx *context.Context){
    	 ctx.Output.Body([]byte("bob"))
    })
    
    //響應到/foo的所有http請求
    beego.Any("/foo",func(ctx *context.Context){
    	 ctx.Output.Body([]byte("bar"))
    })
    

    以注冊handler的方式設置路由

    也可以使用beego.Handler(router, http.Handler)設置路由的handler:

    beego.Handler("/rpc", s)
    

    beego.Handler默認是完全匹配,不是前綴匹配。可以自定義http請求方法和處理函數的映射關系:

    beego.Router("/api/list",&RestController{},"*:ListFood")
    beego.Router("/api/create",&RestController{},"post:CreateFood")
    beego.Router("/api/update",&RestController{},"put:UpdateFood")
    beego.Router("/api/delete",&RestController{},"delete:DeleteFood")
    

    自定義映射關系的格式為”請求方法:函數名”,請求方法有下面幾種:

    *: 包含以下所有的函數,優先級低於下面的方法
    get: GET 請求
    post: POST 請求
    put: PUT 請求
    delete: DELETE 請求
    patch: PATCH 請求
    options: OPTIONS 請求
    head: HEAD 請求
    

    自動注冊路由

    另外還有beego.AutoRouter($controllers.ObjectController{}),會自動通過反射為Object中的方法生成路由。

    通過注解注冊路由

    在controller的方法上面加上router注釋,router.go中通過beego.Include(&Controller)引入controller的時候會自動注冊路由。

    例如:

    // CMS API
    type CMSController struct {
    	beego.Controller
    }
    
    func (c *CMSController) URLMapping() {
    	c.Mapping("StaticBlock", c.StaticBlock)
    	c.Mapping("AllBlock", c.AllBlock)
    }
    
    // @router /staticblock/:key [get]
    func (this *CMSController) StaticBlock() {
    
    }
    
    // @router /all/:key [get]
    func (this *CMSController) AllBlock() {
    
    }
    

    然后在router.go中:

    beego.Include(&CMSController{})
    

    beego會自動進行源碼分析,如果是dev模式,會在routers/commentXXX.go文件。

    使用namespace管理路由

    namespace支持前套,並且可以對包含其中對路由進行前置過濾、條件判斷。

    namespace接口如下:

    NewNamespace(prefix string, funcs …interface{})     初始化 namespace 對象
    NSCond(cond namespaceCond)      支持滿足條件才namespace
    NSBefore(filiterList …FilterFunc)
    NSAfter(filiterList …FilterFunc)
    NSInclude(cList …ControllerInterface)
    NSRouter(rootpath string, c ControllerInterface, mappingMethods …string)
    NSGet(rootpath string, f FilterFunc)
    NSPost(rootpath string, f FilterFunc)
    NSDelete(rootpath string, f FilterFunc)
    NSPut(rootpath string, f FilterFunc)
    NSHead(rootpath string, f FilterFunc)
    NSOptions(rootpath string, f FilterFunc)
    NSPatch(rootpath string, f FilterFunc)
    NSAny(rootpath string, f FilterFunc)
    NSHandler(rootpath string, h http.Handler)
    NSAutoRouter(c ControllerInterface)
    NSAutoPrefix(prefix string, c ControllerInterface)
    

    示例:

    //初始化 namespace
    ns :=
    beego.NewNamespace("/v1",
        beego.NSCond(func(ctx *context.Context) bool {
            if ctx.Input.Domain() == "api.beego.me" {
                return true
            }
            return false
        }),
        beego.NSBefore(auth),
        beego.NSGet("/notallowed", func(ctx *context.Context) {
            ctx.Output.Body([]byte("notAllowed"))
        }),
        beego.NSRouter("/version", &AdminController{}, "get:ShowAPIVersion"),
        beego.NSRouter("/changepassword", &UserController{}),
        beego.NSNamespace("/shop",
            beego.NSBefore(sentry),
            beego.NSGet("/:id", func(ctx *context.Context) {
                ctx.Output.Body([]byte("notAllowed"))
            }),
        ),
        beego.NSNamespace("/cms",
            beego.NSInclude(
                &controllers.MainController{},
                &controllers.CMSController{},
                &controllers.BlockController{},
            ),
        ),
    )
    //注冊 namespace
    beego.AddNamespace(ns)
    

    注冊了以下的路由:

    GET /v1/notallowed
    GET /v1/version
    GET /v1/changepassword
    POST /v1/changepassword
    GET /v1/shop/123
    GET /v1/cms/ 對應 MainController、CMSController、BlockController 中得注解路由
    

    需要特別注意的NSAfter()

    NSAfter()注冊的filter函數會在請求處理結束的時候被調用,但是要注意在bee 1.9.0中:

    beego.NSAfter does not work after controller.ServeJSON
    

    相關的issue:

    注解路由無法進入NSBefore controller.ServeJSON should work will with beego.NSAfter

    可以用github: study-beego里的的代碼試驗一下。

    使用數據庫

    beego仿照Digango ORM和SQLAlchemy實現beego ORM,當前支持三個驅動:

    MySQL:github.com/go-sql-driver/mysql
    PostgreSQL:github.com/lib/pq
    Sqlite3:github.com/mattn/go-sqlite3
    

    beego生成的model文件中,會自動將model注冊到orm,例如:

    bee generate model user -fields="name:string,age:int"
    

    生成的代碼models/user.go中會在init()中注冊:

    func init() {
    	orm.RegisterModel(new(User))
    }
    

    因此只需要手工書寫orm初始化的代碼,譬如在main.go中:

    func init() {
    	orm.RegisterDataBase("default", "mysql", "root:@tcp(127.0.0.1:3306)/mysql?charset=utf8", 30)
    }
    

    數據庫遷移(migration)

    數據庫遷移功能可以數據庫進行升級、回滾操作。

    生成遷移文件,user是表名,fields是表結構:

    bee generate migration user -driver=mysql -fields="name:string,age:int"
    

    運行后,生成了文件:

    |____database
    | |____migrations
    | | |____20171024_154037_user.go
    

    在數據庫中創建了名為study-beego的數據庫后,執行下面的命令:

    bee migrate -driver=mysql -conn="root:@tcp(127.0.0.1:3306)/study-beego"
    

    study-beego中的表將會被創建或者更新,並在名為migrations的表中記錄更新。

    bee migrate

    migrate的子命令refreshrollback執行失敗,原因不明。

    beego.Controller處理http請求

    注意,在1.9.0中,需要在配置中設置copyrequestbody=true以后,c.Ctx.Input.RequestBody中才有數據。

    func (c *UserController) Post() {
    	var v models.User
    	json.Unmarshal(c.Ctx.Input.RequestBody, &v)
    	fmt.Println(v)
    	if _, err := models.AddUser(&v); err == nil {
    		c.Ctx.Output.SetStatus(201)
    		c.Data["json"] = v
    	} else {
    		c.Data["json"] = err.Error()
    	}
    	c.ServeJSON()
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM