Beego脱坑(三)Router - Go语言中文社区

Beego脱坑(三)Router



title: Beego脱坑(三)Router
tags: go,beego
author : Clown95


beego中的路由的主要功能是实现从请求地址到实现方法 ,简单的说就是路由就是能够自动匹配url地址,并调用相应的控制器处理信息。

在之前创建beego项目中,我们为了完成hello world的输出,在 router.go 中添加了

beego.Router("/hello",&controllers.HelloControllers{})

我们这段代码的意思就是把 /hello 这个地址分配给 HelloControllers 这个控制器去处理。

简单路由

我们先来了解下最基本的 GET路由和PSOT路由。

GET路由

func (hello * HelloControllers) Get() {
    hello.Ctx.WriteString("hello worldn")
}

还记得我们之前写hello.go的代码吗?我们是通过HelloControllers控制器,执行Get方法,来输出 hello world

现在我们不通过控制器,直接使用GET路由来输出 Hello Beego

package routers

import (

    "github.com/astaxie/beego/context"
)

func init() {
    /**/
    beego.Get("hello1", func(context *context.Context) {
        context.WriteString("Hello Beegon")
    })
}

我们运行程序,并且打开请求可以看到,成功的输出了 Hello Beego ,日志中显示的是 GET 请求。

image
image

POST路由

接着我们再来说下POST路由,我们把刚刚的代码简单修改下

beego.Post("hello2", func(context *context.Context) {
    context.WriteString("Hello Beegon")
})

现在我们执行的是POST请求,直接使用浏览器打开肯定是不行的。

image

所以我们使用postman模拟下post请求

image

固定路由

那么固定路由又是什么呢?从字面意思理解是不会改变的路由,我们刚刚使用的 /hello /hello1 /hello2 都可以被成为固定路由。

只有我们正确的输入才能够匹配到相应的结果,即完全匹配,比如说输入/hello 只会匹配到 hello world ,而不会匹配到 hello beego。

正则路由

正则路由则跟固定路由有所区别了,它并不需要完全匹配,只需要符合这个路由所设置的规则即可,我们来演示下。

先添加路由

beego.Router("/Api/?:id",&controllers.RegularController{}) //我们定义一个正则路由

在controllers目录下创建 reg.go文件

package controllers

import "github.com/astaxie/beego"

type RegularController struct {
    beego.Controller
}
func (reg * RegularController) Get() {
    id:= reg.Ctx.Input.Param(":id")
    reg.Ctx.WriteString("id="+id+"n")
}

我们来看下多次运行结果:

image

正则路由就是能够让我们更灵活的匹配内容,并且减少开发者的代码量

https://blog.csdn.net/yang731227/article/details/82251316 比如说我们看CSDN这个文章地址,文章控制器都是通用的,我们没必要为每一篇文章都添加一个控制器,我们看这个地址中文章编号已经是8000多万了,我们想象下写8000多万个控制器是什么概念,即使我们有那功夫写这么多控制器,那也是不可行的,因为这个文章数是不确定的,用户可能会增加文章或者删除文章,我们不可能完全一一对应,所以使用根据一定的规则来写路由是这类型地址的最佳选择。

更多正则路由说明,请查看官方文档https://beego.me/docs/mvc/controller/router.md#%E6%AD%A3%E5%88%99%E8%B7%AF%E7%94%B1

自定义方法及 RESTful 规则

我们上面的请求方法,不是GET就是POST,那我们能不能自定义请求方法呢?答案是肯定的

我们先来看下面的一行代码,可以看到它既没有使用GET也没有使用POST

beego.Router("/",&IndexController{},"*:Index")

我们之前使用Router都是只传递了两个参数,上面的代码增加了一个参数,那么这第三个参数能干什么?

第三个参数就是用来设置对应 method 到函数名,定义如下

  • *表示任意的 method 都执行该函数
  • 使用 httpmethod:funcname 格式来展示
  • 如果想要使用多个不同的方法使用 ; 分割
  • 多个 method 对应同一个 funcname,method 之间通过 , 来分割

我们来演示下自定义方法:

创建文件 Custom.go

package controllers

import (

    "github.com/astaxie/beego"
)

type CustomController struct {
    beego.Controller
}

func (this *CustomController) GetFunc() {
    username := this.GetString("username")
    password := this.GetString("password")
    this.Ctx.WriteString("username = " + username + "npassword = " + password + "n用于处理get请求")

}

注册路由:

    beego.Router("/rest",&controllers.CustomController{},"Get:GetFunc")

执行地址;

image

刚刚演示了一个自定义的Get方法,现在我们就来改成Post

func (this *CustomController) PostFunc() {
    username := this.GetString("username")
    password := this.GetString("password")
    this.Ctx.WriteString("username = " + username + "npassword = " + password + "n用于处理post请求")

}

我们在之前的路由后面追加Post方法

    beego.Router("/rest",&controllers.CustomController{},"Get:GetFunc;Post:PostFunc")

使用PostMan模拟请求

image

除了Get:GetFunc 和Post:PostFunc。我们还可以定义 *:AllFunc,即两个方法都可以,具体的演示这里不在叙述,如果有不明白的地方可以查看官方文档。

如果同时存在 * 和对应的 HTTP Method,那么优先执行 HTTP Method 的方法,如执行的时候请求了Post,首先执行的是PostFunc而不是AllFunc。

值得注意的是:不要被GetFunc 、PostFunc和AllFunc 这些方法名混淆,并不是强制要求这么写,这些名字可以是任意符合方法命名规则的名字。

自动匹配

自动匹配比较有意思,它不需要我们指定请求地址,它可以根据我们传来的请求自动匹配方法。这么说是不是有点迷惑?没关系我们还是来看代码:

package controllers

import (
    "github.com/astaxie/beego"
)

type AutoController struct {
    beego.Controller
}

func (this *AutoController) GetFunc(){
     p:=this.Ctx.Input.Params() //Params是解析多个参数,返回map
     for k,v:=range  p{
         this.Ctx.WriteString(k+"="+v+"n")
     }

}

下面注意路由使用的函数,我们可以清楚的看到 beego调用了 AutoRouter 函数并且参数只有一个控制器。

beego.AutoRouter(&controllers.AutoController{})

AutoRouter的实现原理是反射,具体细节可以自己看golang代码研究。

小伙伴们是不是不知道怎么填写地址了?没有关系先跟着我们来,我们在浏览器或者使用Curl命令打开
http://localhost:8080/Auto/GetFunc/123/456

image

我们先来简单了解下 AutoRouter怎么匹配的 ,通过地址我们可以猜想,Auto/GetFunc这段的意思是先匹配AutoController控制器,然后执行GetFunc 这个方法 ,接着解析123/456 这两个参数。除了前缀两个 /:controller(控制器名称)/:method(函数名称) 的匹配之外,剩下的 url beego 会帮你自动化解析为参数,保存在 this.Ctx.Input.Params 当中。

有一个点必须要强调,首先我们先来看下我们定义的所有控制的名字 HelloController 、RegularController 、CustomController 和 AutoController 你是不是发现了什么?对没错我们的控制器都是以 xxxController 命名的。自动匹配就会根据地址自动匹配xxx,所以使用自动匹配,控制器的名字一定要符合规则,不然会提示404的。

注解路由

什么是注解路由?注解路由就是我们不需要在router.go中注册路由了,只需要在相对应的controller上方写上一定格式的注释,即可注册路由。

注解路由的格式为:

// @router /xxx/:key [get]

必须以@router开头 然后 / 后面是制定地址 接着后面是参数 [get]是表示get的传递方式 。

现在我们把 /hello 这个固定路由改造下,改成注解路由。

比如说我们之前注册的 HelloController 路由,正常的方法是在router.go 中添加下面代码

beego.Router("/hello",&controllers.HelloController{})

现在我们使用include注册注解路由,替换上面固定路由。

beego.Include(&controllers.HelloController{})

然后在控制器方法上方,添加注解路由

// @router /hello
func (hello * HelloController) Get() {
    hello.Ctx.WriteString("hello worldn")
}

然后我们执行程序,成功的调用了HelloController 控制器

image

URLMapping

在新版中beego 可以使用URLMapping 方法来指定执行对应函数,提高注解路由性能。

具体用法如下:

// @router /hello
func (hello * HelloController) Get() {
    hello.Ctx.WriteString("hello worldn")
}

func (hello * HelloController) URLMapping() {
    hello.Mapping("Get",hello.Get)
}

对于注解路由,我个人是不太建议使用,虽然这个写法可以很直观的看到是什么请求调用什么方法,但是我感觉还是比较容易踩坑。首先它效率上比不上固定路由或者正则路由,而且有时候可能会匹配不到控制器,比如说我之前遇到过如果我不为控制器添加URLMapping方法,请求怎么都匹配不到控制器,所以我们真的没必要使用注解路由。

版权声明:本文来源简书,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://www.jianshu.com/p/d0d1462113d4
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-01-12 11:55:48
  • 阅读 ( 1244 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢