提示:在 v1.6 中,此文檔所涉及的 API 有重大變更,this.ServeJson() 更改為 this.ServeJSON(),this.TplNames 更改為 this.TplName。
基于 beego 的 Controller 設(shè)計(jì),只需要匿名組合 beego.Controller 就可以了,如下所示:
type xxxController struct {
beego.Controller
}
beego.Controller 實(shí)現(xiàn)了接口 beego.ControllerInterface,beego.ControllerInterface 定義了如下函數(shù):
所以通過(guò)子 struct 的方法重寫(xiě),用戶就可以實(shí)現(xiàn)自己的邏輯,接下來(lái)我們看一個(gè)實(shí)際的例子:
type AddController struct {
beego.Controller
}
func (this *AddController) Prepare() {
}
func (this *AddController) Get() {
this.Data["content"] = "value"
this.Layout = "admin/layout.html"
this.TplName = "admin/add.tpl"
}
func (this *AddController) Post() {
pkgname := this.GetString("pkgname")
content := this.GetString("content")
pk := models.GetCruPkg(pkgname)
if pk.Id == 0 {
var pp models.PkgEntity
pp.Pid = 0
pp.Pathname = pkgname
pp.Intro = pkgname
models.InsertPkg(pp)
pk = models.GetCruPkg(pkgname)
}
var at models.Article
at.Pkgid = pk.Id
at.Content = content
models.InsertArticle(at)
this.Ctx.Redirect(302, "/admin/index")
}
從上面的例子可以看出來(lái),通過(guò)重寫(xiě)方法可以實(shí)現(xiàn)對(duì)應(yīng) method 的邏輯,實(shí)現(xiàn) RESTful 結(jié)構(gòu)的邏輯處理。
下面我們?cè)賮?lái)看一種比較流行的架構(gòu),首先實(shí)現(xiàn)一個(gè)自己的基類(lèi) baseController,實(shí)現(xiàn)一些初始化的方法,然后其他所有的邏輯繼承自該基類(lèi):
type NestPreparer interface {
NestPrepare()
}
// baseRouter implemented global settings for all other routers.
type baseController struct {
beego.Controller
i18n.Locale
user models.User
isLogin bool
}
// Prepare implemented Prepare method for baseRouter.
func (this *baseController) Prepare() {
// page start time
this.Data["PageStartTime"] = time.Now()
// Setting properties.
this.Data["AppDescription"] = utils.AppDescription
this.Data["AppKeywords"] = utils.AppKeywords
this.Data["AppName"] = utils.AppName
this.Data["AppVer"] = utils.AppVer
this.Data["AppUrl"] = utils.AppUrl
this.Data["AppLogo"] = utils.AppLogo
this.Data["AvatarURL"] = utils.AvatarURL
this.Data["IsProMode"] = utils.IsProMode
if app, ok := this.AppController.(NestPreparer); ok {
app.NestPrepare()
}
}
上面定義了基類(lèi),大概是初始化了一些變量,最后有一個(gè) Init 函數(shù)中那個(gè) app 的應(yīng)用,判斷當(dāng)前運(yùn)行的 Controller 是否是 NestPreparer 實(shí)現(xiàn),如果是的話調(diào)用子類(lèi)的方法,下面我們來(lái)看一下 NestPreparer 的實(shí)現(xiàn):
type BaseAdminRouter struct {
baseController
}
func (this *BaseAdminRouter) NestPrepare() {
if this.CheckActiveRedirect() {
return
}
// if user isn't admin, then logout user
if !this.user.IsAdmin {
models.LogoutUser(&this.Controller)
// write flash message
this.FlashWrite("NotPermit", "true")
this.Redirect("/login", 302)
return
}
// current in admin page
this.Data["IsAdmin"] = true
if app, ok := this.AppController.(ModelPreparer); ok {
app.ModelPrepare()
return
}
}
func (this *BaseAdminRouter) Get(){
this.TplName = "Get.tpl"
}
func (this *BaseAdminRouter) Post(){
this.TplName = "Post.tpl"
}
這樣我們的執(zhí)行器執(zhí)行的邏輯是這樣的,首先執(zhí)行 Prepare,這個(gè)就是 Go 語(yǔ)言中 struct 中尋找方法的順序,依次往父類(lèi)尋找。執(zhí)行 BaseAdminRouter 時(shí),查找他是否有 Prepare 方法,沒(méi)有就尋找 baseController,找到了,那么就執(zhí)行邏輯,然后在 baseController 里面的 this.AppController 即為當(dāng)前執(zhí)行的控制器 BaseAdminRouter,因?yàn)闀?huì)執(zhí)行 BaseAdminRouter.NestPrepare 方法。然后開(kāi)始執(zhí)行相應(yīng)的 Get 方法或者 Post 方法。
我們應(yīng)用中經(jīng)常會(huì)遇到這樣的情況,在 Prepare 階段進(jìn)行判斷,如果用戶認(rèn)證不通過(guò),就輸出一段信息,然后直接中止進(jìn)程,之后的 Post、Get 之類(lèi)的不再執(zhí)行,那么如何終止呢?可以使用 StopRun 來(lái)終止執(zhí)行邏輯,可以在任意的地方執(zhí)行。
type RController struct {
beego.Controller
}
func (this *RController) Prepare() {
this.Data["json"] = map[string]interface{}{"name": "astaxie"}
this.ServeJSON()
this.StopRun()
}
調(diào)用 StopRun 之后,如果你還定義了 Finish 函數(shù)就不會(huì)再執(zhí)行,如果需要釋放資源,那么請(qǐng)自己在調(diào)用 StopRun 之前手工調(diào)用 Finish 函數(shù)。
首先要說(shuō)明, 在 XHTML 1.x 標(biāo)準(zhǔn)中, 表單只支持 GET 或者 POST 方法. 雖然說(shuō)根據(jù)標(biāo)準(zhǔn), 你不應(yīng)該將表單提交到 PUT 方法, 但是如果你真想的話, 也很容易, 通??梢赃@么做:
首先表單本身還是使用 POST 方法提交, 但是可以在表單中添加一個(gè)隱藏字段:
<form method="post" ...>
<input type="hidden" name="_method" value="put" />
接著在 Beego 中添加一個(gè)過(guò)濾器來(lái)判斷是否將請(qǐng)求當(dāng)做 PUT 來(lái)解析:
var FilterMethod = func(ctx *context.Context) {
if ctx.BeegoInput.Query("_method")!="" && ctx.BeegoInput.IsPost(){
ctx.Request.Method = ctx.BeegoInput.Query("_method")
}
}
beego.InsertFilter("*", beego.BeforeRouter, FilterMethod)
更多建議: