• beego——控制器函数


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

    type xxxController struct {
        beego.Controller
    }
    

    beego.Controller实现了接口beego.ControllerInterface,其源码定义如下:

    // ControllerInterface is an interface to uniform all controller handler.
    type ControllerInterface interface {
            Init(ct *context.Context, controllerName, actionName string, app interface{})
            Prepare()
            Get()
            Post()
            Delete()
            Put()
            Head()
            Patch()
            Options()
            Finish()
            Render() error
            XSRFToken() string
            CheckXSRFCookie() bool
            HandlerFunc(fn string) bool
            URLMapping()
    }
    

    部分解释:

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

        这个函数主要初始化了Context、相应的Controller名称、模板名、初始化模板参数的容器Data,

        app即为当前执行的Controller的reflecttype,这个app可以用来执行子类的方法。

      (2)Prepare()

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

      (3)Get()、Post()、Delete()、Put()、Head()、Patch()、Options()

        这些函数都是用户请求的方法,用户请求的HTTP Method是什么就执行什么函数,默认是405,用户继承的子struct中可以实现该方法以处理相对应的请求。

      (4)Finish()

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

      (5)Render() error

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

    通过重写struct的方法,我们就可以实现自己的逻辑。

    示例1:

    package control
    
    import (
    	"github.com/astaxie/beego"
    )
    
    //重写struct,定义自己的逻辑
    type AddController struct {
    	beego.Controller
    }
    
    //定义prepare方法
    func (this *AddController) Prepare() {
    	
    }
    
    //定义Post方法
    func (this *AddController) Post() {
    	pkgname := this.GetString("pkgname")
    	content := this.GetString("content")
    	pk := models.GetCruPkg(pkgname)
    	if pk.Id == 0 {
    		var pp model.PkgEntitiy
    		pp.Pid = 0
    		pp.Pathname = pkgname
    		pp.Intro = pkgname
    		model.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")  //返回状态码,以及跳转到对应的页面
    }
    
    //之后,修改路由,就可以使用自己的逻辑处理请求
    //beego.Router("/user", &controllers.AddController{})
    

      

    下面展示一种常用的架构,首先实现一个自己的基类,实现一些初始化方法,然后,其它所有的逻辑继承自该基类。

    示例2:

    type NestPreparer interface {
            NestPrepare()
    }
    
    // baseRouter为所有其他路由器实现全局设置。
    type baseController struct {
            beego.Controller
            i18n.Locale
            user    models.User
            isLogin bool
    }
    //定义prepare方法
    func (this *baseController) Prepare() {
    
            // 页面开始时间
            this.Data["PageStartTime"] = time.Now()
    
            //参数配置
            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()
            }
    }
    
    //this.Data是一个用来存储输出数据的map,可以赋值任意类型的值。
    

      

    上面定义了基类,大概是初始化了一些变量,最后有一个init函数中那个app应用,

    判断当前运行的Controller是否是NestPreparer实现,如果是的话就调用子类的方法。下面看一下NestPreparer的实现。

    示例三:

    type BaseAdminRouter struct {
    	baseController
    }
    
    //定义方法
    func (this *BaseAdminRouter) NestPrepare() {
    	if this.CheckActiveRedirect() {
    		return
    	}
    
    	//当前用户不是admin,退出
    	if !this.user.IsAdmin {
    		models.LogoutUser(&this.Controller)
    
    		// 写入flash信息
    		this.FlashWrite("NotPermit", "true")
    		//跳转
    		this.Redirect("/login", 302)
    		return
    	}
    
    	// 当前管理页面
    	this.Data["IsAdmin"] = true
    
    	if app, ok := this.AppController.(ModelPreparer); ok {
    		app.ModelPrepare()
    		return
    	}
    }
    
    //定义get方法
    func (this *BaseAdminRouter) Get() {
    	this.TplName = "Get.tpl"
    }
    
    //定义post方法
    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来终止执行逻辑,可以在任意的地方执行。

    示例3:

    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方法,但是如果你真想的话,也很容易,通常可以这么做:

    (1)首先表单本身还是使用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)
  • 相关阅读:
    总结mysql服务器查询慢原因与解决方法
    mysql查询今天,昨天,近7天,近30天,本月,上一月数据的方法
    Github 终于开始认真考虑开源项目许可证了
    mysql 外连接总结
    MYSQL--事务处理
    MySQL 索引详解
    MySQL数据库优化总结
    Delphi 2010 安装及调试
    Delphi 2010
    PostgreSQL 8.4.1
  • 原文地址:https://www.cnblogs.com/yangmingxianshen/p/10117568.html
Copyright © 2020-2023  润新知