控制器介绍

提示:在 v1.6 中,此文档所涉及的 API 有重大变更,this.ServeJson() 更改为 this.ServeJSON()this.TplNames 更改为 this.TplName

基于 beego 的 Controller 设计,只需要匿名组合 beego.Controller 就可以了,如下所示:

type xxxController struct {
beego.Controller
}

beego.Controller 实现了接口 beego.ControllerInterfacebeego.ControllerInterface 定义了如下函数:

  • Init(ct *context.Context, childName string, app interface{})

    这个函数主要初始化了 Context、相应的 Controller 名称,模板名,初始化模板参数的容器 Data,app 即为当前执行的 Controller 的 reflecttype,这个 app 可以用来执行子类的方法。

  • Prepare()

    这个函数主要是为了用户扩展用的,这个函数会在下面定义的这些 Method 方法之前执行,用户可以重写这个函数实现类似用户验证之类。

  • Get()

    如果用户请求的 HTTP Method 是 GET,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Get 请求。

  • Post()

    如果用户请求的 HTTP Method 是 POST,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Post 请求。

  • Delete()

    如果用户请求的 HTTP Method 是 DELETE,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Delete 请求。

  • Put()

    如果用户请求的 HTTP Method 是 PUT,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Put 请求.

  • Head()

    如果用户请求的 HTTP Method 是 HEAD,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Head 请求。

  • Patch()

    如果用户请求的 HTTP Method 是 PATCH,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Patch 请求.

  • Options()

    如果用户请求的HTTP Method是OPTIONS,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Options 请求。

  • Finish()

    这个函数是在执行完相应的 HTTP Method 方法之后执行的,默认是空,用户可以在子 struct 中重写这个函数,执行例如数据库关闭,清理数据之类的工作。

  • Render() error

    这个函数主要用来实现渲染模板,如果 beego.AutoRender 为 true 的情况下才会执行。

所以通过子 struct 的方法重写,用户就可以实现自己的逻辑,接下来我们看一个实际的例子:

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")
}

从上面的例子可以看出来,通过重写方法可以实现对应 method 的逻辑,实现 RESTful 结构的逻辑处理。

下面我们再来看一种比较流行的架构,首先实现一个自己的基类 baseController,实现一些初始化的方法,然后其他所有的逻辑继承自该基类:

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()
}
}
/*
分析一线init方法的实现过程
c.AppController 代表接口,可以调用子类的方法
this.AppController.(NestPreparer)
判断当前运行的 Controller 是否是 NestPreparer 实现
 
// Init generates default values of controller operations.
func (c *Controller) Init(ctx *context.Context, controllerName, actionName string, app interface{}) {
	c.Layout = ""
	c.TplName = ""
	c.controllerName = controllerName
	c.actionName = actionName
	c.Ctx = ctx
	c.TplExt = "tpl"
	c.AppController = app
	c.EnableRender = true
	c.EnableXSRF = true
	c.Data = ctx.Input.Data()
	c.methodMapping = make(map[string]func())
}


*/

上面定义了基类,大概是初始化了一些变量,最后有一个 Init 函数中那个 app 的应用,判断当前运行的 Controller 是否是 NestPreparer 实现,如果是的话调用子类的方法,下面我们来看一下 NestPreparer 的实现:

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"
}

这样我们的执行器执行的逻辑是这样的,首先执行 Prepare,这个就是 Go 语言中 struct 中寻找方法的顺序,依次往父类寻找。执行 BaseAdminRouter 时,查找他是否有 Prepare 方法,没有就寻找 baseController,找到了,那么就执行逻辑,然后在 baseController 里面的 this.AppController 即为当前执行的控制器 BaseAdminRouter,因为会执行 BaseAdminRouter.NestPrepare 方法。然后开始执行相应的 Get 方法或者 Post 方法。

提前终止运行

我们应用中经常会遇到这样的情况,在 Prepare 阶段进行判断,如果用户认证不通过,就输出一段信息,然后直接中止进程,之后的 Post、Get 之类的不再执行,那么如何终止呢?可以使用 StopRun 来终止执行逻辑,可以在任意的地方执行。

type RController struct {
beego.Controller
} func (this *RController) Prepare() {
this.Data["json"] = map[string]interface{}{"name": "astaxie"}
this.ServeJSON()
this.StopRun()
}

调用 StopRun 之后,如果你还定义了 Finish 函数就不会再执行,如果需要释放资源,那么请自己在调用 StopRun 之前手工调用 Finish 函数。

在表单中使用 PUT 方法

首先要说明, 在 XHTML 1.x 标准中, 表单只支持 GET 或者 POST 方法. 虽然说根据标准, 你不应该将表单提交到 PUT 方法, 但是如果你真想的话, 也很容易, 通常可以这么做:

首先表单本身还是使用 POST 方法提交, 但是可以在表单中添加一个隐藏字段:

<form method="post" ...>
<input type="hidden" name="_method" value="put" />

接着在 Beego 中添加一个过滤器来判断是否将请求当做 PUT 来解析:

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)

beego控制器介绍的更多相关文章

  1. beego——控制器函数

    基于beego的Controller设计,只需要匿名组合beego.Controller就可以,如下所示: type xxxController struct { beego.Controller } ...

  2. 7. Jmeter-逻辑控制器介绍与使用

    逻辑控制器介绍与使用 如果(if)控制器 事物控制器 循环控制器 while controller critical section controller foreach控制器 include con ...

  3. PID控制器介绍

    在维基百科上查到的PID的介绍,收藏一下,慢慢看. https://zh.wikipedia.org/wiki/PID%E6%8E%A7%E5%88%B6%E5%99%A8#%E6%AF%94%E4% ...

  4. CAN协议学习(二)MCAN控制器介绍

    更多细节请参看MCAN2文档mcan2_ps.pdf. 一.MCAN2简介 MCAN2是Mentor公司开发的一个CAN2.0网络控制器的软核,初版2001年末版2006年.MCAN 2控制器实现了B ...

  5. beego学习2 控制器与路由

    beego控制器 controller目录新建test.go文件 结构体集成beego.Controller 控制名需大写,否则为私有方法 package controllers import ( & ...

  6. iOS:模态弹出窗控制器UIPopoverPresentationController

    模态弹出窗控制器:UIPopoverPresentationController 实质:就是将内容控制器包装成PopoverPresentationController的形式,然后再模态出来,必须指定 ...

  7. ARM 之LCD和LCD控制器

    既然提到 了LCD那么我们首先必须要了解的就是他的种类,CD(liquid crystal  display), 即液晶显示器,是这一种采用了液晶控制透光度计数来实现色彩的显示器,他与传统的CRT显示 ...

  8. ABP官方文档翻译 6.1.1 MVC控制器

    ASP.NET MVC控制器 介绍 AbpController基类 本地化 其他 过滤器 异常处理和结果包装 审计日志 验证 授权 工作单元 介绍 ABP通过Abp.Web.Mvc nuget包集成到 ...

  9. ABP官方文档翻译 5.1 Web API控制器

    ASP.NET Web API控制器 介绍 AbpApiController基类 本地化 其他 过滤器 审计日志 授权 反伪造过滤器 工作单元 结果包装和异常处理 结果缓存 校验 模型绑定器 介绍 A ...

随机推荐

  1. MySQL复制(四)—多源(主)复制

    (一)多主复制概述 MySQL从5.7版本开启支持多主复制,所谓多主复制,是将多个主库的数据复制到一个从库中.通常用于数据仓库整合数据,比如OLTP系统为了分散业务压力,对数据库进行分库分表,当要对数 ...

  2. ORB-SLAM2 论文&代码学习 ——Tracking 线程

    本文要点: ORB-SLAM2 Tracking 线程 论文内容介绍 ORB-SLAM2 Tracking 线程 代码结构介绍 写在前面 上一篇文章中我们已经对 ORB-SLAM2 系统有了一个概览性 ...

  3. Linux中awk抽取包含某字段的整行日志

    命令示例:awk '{if($0~"listAuths") print}'   xxx.log 解释说明:抽取xxx.log整个日志文件中,包含“listAuths”的行,打印输出

  4. css架构技巧

    1. 写一个reset.css 用于清除浏览器标签默认样式并定义全局样式,这样就不会因为浏览器默认样式出现问题,因为不同浏览器的默认样式还是不一样的

  5. Nginx简介入门

    买了极客时间上陶辉的Nginx核心知识100讲,正在学.链接 Nginx 4个组成部分 二进制可执行文件 nginx.conf 配置文件 access.log error.log nginx 版本 M ...

  6. [Python]判断变量类型是否为List列表

    用法:isinstance(变量,list) li = [1,2,3] print(type(li)) if isinstance(li,list): print("This is a Li ...

  7. centos 配置虚拟环境

    1.pip install virtualenvwrapper (pip install virtualenv virtualenvwrapper)2.export WORKON_HOME=/home ...

  8. 修改centos7容器的时间和宿主机时间一致

    一.问题 centos7系统容器时间与宿主机系统时间不一致,就进去查看一番,发现时区和宿主机上的时间不一致,下面就来解决一下 二.现象 1.查看centos宿主机的时间 输入如下命令查看 # date ...

  9. C# 数据类型详解以及变量、对象与内存

    学习刘铁猛老师<C#语言入门详解>视频,针对其中重点知识点进行总结. 1.什么是类型? 类型又称为数据类型(Data Type),数据类型在数据结构中的定义是一个值的集合以及定义在这个值集 ...

  10. NetCore3.0实现自定义IOC容器注入

    在之前的ASP.NET MVC实现依赖注入一文中,通过替换默认的ControllerFactory来达到对Controller生命周期的拦截,实现自定义的对象注入,在NetCore3.0中需要重新实现 ...