Beego 添加路由功能
beego 添加路由功能通过修改 routers->router.go 文件来实现,beego 实现路由的方式有多种,参考文档:
https://beego.me/docs/mvc/controller/router.md,在这里我们使用注解路由
beego 的控制器有很多种方法,其中包括 Init、Prepare等方法。其中 Prepare 方法是每次请求都会调用的方法,看源
码如下:
// Prepare runs after Init before request function execution. func (c *Controller) Prepare() {}
这个方法是一个空方法,我们需要创建一个基类重写 Prepare 方法
1.首先创建一个 controllers->base.go ,新增结构体 BaseController 继承 beego.Controller ,为 BaseController 添加
Prepare 方法,所有继承了 BaseController 的字 controller 每次请求都会调用 Prepare 方法,在这里我们约定所有的子
controller 都会继承 BaseController ,可以将每次请求的通用逻辑写在 BaseController 的 Prepare 方法里
2.如果子 controller 里面的所有方法除了调用 BaseController 里面的 PrePare 方法的通用逻辑外,还有一些当前子 con
troller 的通用逻辑怎么办?难道当前子 controller 的每个方法都要重写一遍吗?我们可以在 BaseController 里面定义个接口
,然后在 BaseController 里面的 Prepare 方法判断子 controller 是否实现了接口,如果实现了就调用接口方法
package controllers import ( "github.com/astaxie/beego" "log" ) // 约定: 如果子 controller 存在 NestPrepare 方法,就实现了该接口 type NestPrepare interface { NestPrepare() } type BaseController struct { beego.Controller } // 重写 Prepare 方法 func (ctx *BaseController) Prepare() { log.Println("BaseController") // 判断子 controller 是否实现了 NestPrepare 接口,如果实现了就调用接口方法 if app,ok := ctx.AppController.(NestPrepare);ok{ app.NestPrepare() } }
3.上面定义了基础控制器 BaseController ,下面新增一个 controllers->index.go 文件,定义 IndexController 文件如下:
package controllers type IndexController struct { BaseController } // 首页 // @router / [get] func (c *IndexController) Get() { c.TplName = "index.html" } // 留言 // @router /message [get] func (c *IndexController) GetMessage() { c.TplName = "message.html" } // 关于 // @router /about [get] func (c *IndexController) GetAbout() { c.TplName = "about.html" }
4.上面定义了 3 个路由以及对应的处理方法,下面我们 routers->router.go 调整一下才能生效
package routers import ( "github.com/astaxie/beego" "liteblog/controllers" ) func init() { // 注解路由 beego.Include(&controllers.IndexController{}) }
5.在上我们已经把路由定义好了,我们现在来调整一下前端代码
5.1修改 header.html 将路由路径改成上面已经定义好的
<div class="header"> <div class="header-wrap"> <h1 class="logo pull-left"> <a href="index.html"> <img src="/static/images/logo.png" alt="" class="logo-img"> <img src="/static/images/logo-text.png" alt="" class="logo-text"> </a> </h1> <form class="layui-form blog-seach pull-left" action=""> <div class="layui-form-item blog-sewrap"> <div class="layui-input-block blog-sebox"> <i class="layui-icon layui-icon-search"></i> <input type="text" name="title" lay-verify="title" autocomplete="off" class="layui-input"> </div> </div> </form> <!-- 这段是调整的部分 开始 --> <div class="blog-nav pull-right"> <ul class="layui-nav pull-left"> <li class="layui-nav-item"><a href="/">首页</a></li> <li class="layui-nav-item"><a href="/message">留言</a></li> <li class="layui-nav-item layui-this"><a href="/about.html">关于</a></li> </ul> <a href="#" class="personal pull-left"> <i class="layui-icon layui-icon-username"></i> </a> </div> <div class="mobile-nav pull-right" id="mobile-nav"> <a href="javascript:;"> <i class="layui-icon layui-icon-more"></i> </a> </div> </div> <!-- 手机打开的路由 --> <ul class="pop-nav" id="pop-nav"> <li><a href="/">首页</a></li> <li><a href="/message">留言</a></li> <li><a href="/about">关于</a></li> </ul> <!-- 调整部分 结束 --> </div>
5.2 调整 layui-this 属性
<div class="blog-nav pull-right"> <ul class="layui-nav pull-left"> <li class="layui-nav-item"><a href="/">首页</a></li> <li class="layui-nav-item"><a href="/message">留言</a></li> <li class="layui-nav-item layui-this"><a href="/about.html">关于</a></li> </ul> <a href="#" class="personal pull-left"> <i class="layui-icon layui-icon-username"></i> </a> </div>
上面这段代码,我们发现 layui-this 属性被写死了,这个属性应该根据当前的页面选择对应的 li,那么这就需要拿到
当前页面的路径,还要有方法去判断路径是否相同
5.2.1 获取当前页面的路径,属于通用功能,需要写在 BaseController 的 Prepare 方法,添加变量的输出
func (ctx *BaseController) Prepare() { // 将当前页面的路径保存到 Path 变量里面 ctx.Data["Path"] = ctx.Ctx.Request.RequestURI // 判断子 controller 是否实现了 NestPrepare 接口,如果实现了就调用接口方法 if app,ok := ctx.AppController.(NestPrepare);ok{ app.NestPrepare() } }
5.2.2 beego 模板自定义
beego 中模板渲染可以自定义方法,模板自定义方法,定义的方式为:
beego.AddFuncMap("模板中调用的方法名",具体函数)
我们现在自定义一个 equrl 模板方法,用来判断路径是否相同,写在 main.go 中:
package main import ( _ "liteblog/routers" "github.com/astaxie/beego" "strings" ) func main() { initTemplate() beego.Run() } // 判断路径是否相同 func initTemplate() { beego.AddFuncMap("equrl", func(x,y string) bool { s1 := strings.Trim(x,"/") s2 := strings.Trim(y,"/") return strings.Compare(s1 ,s2) == 0 }) }
5.2.3 修改views->comm->header.html 里面的代码,加上路径比较的逻辑
<ul class="layui-nav pull-left"> <li class="layui-nav-item {{if equrl "/" .Path}} layui-this {{end}}"><a href="/">首页</a></li> <li class="layui-nav-item {{if equrl "/message" .Path}} layui-this {{end}}"><a href="/message">留言</a></li> <li class="layui-nav-item {{if equrl "/about" .Path}} layui-this {{end}}"><a href="/about.html">关于</a></li> </ul>
6.错误页面处理
如果我们访问的地址不存在,页面会怎么样?beego 提供了一个默认的错误页面,一般我们需要根据项目的需求定制一个
符合自己的错误页面,因此需要修改 beego 的默认错误页面
6.1 添加个controllers->error.go 文件,定义 ErrorController 的控制器,里面定义好 Error404 方法,代码如下:
package controllers type ErrorController struct { BaseController } func (c *ErrorController) Error404() { c.Data["content"] = "page not found" c.TplName = "404.html" }
6.2接着将 ErrorController 注入到 beego 里面,修改默认的错误页面处理,修改方法是 beego.ErrorController (错误控制器),
修改 router.go 文件,代码如下:
func init() { // 注解路由 需要调用 Include beego.ErrorController(&controllers.ErrorController{}) beego.Include(&controllers.IndexController{}) }
注意:golang 引入包的地方出现 "_" 表示调用 xxx 包下的 init 方法,main.go 为入口函数,没有调用 router.go 的任意函数,但是
注意引入包的地方有 _ "liteblog/routers" ,就默认调用 rotuters 包下的 init 方法