Beego脱坑(三)Router

· · 566 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

---

title: Beego脱坑(三)Router

tags: go,beego

author : Clown95

---

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

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

```go

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

```

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

# 简单路由

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

## GET路由

```go

func (hello * HelloControllers) Get() {

hello.Ctx.WriteString("hello world\n")

}

```

还记得我们之前写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 Beego\n")

})

}

```

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

![](https://raw.githubusercontent.com/Clown95/StroyBack/master/小书匠/1573998257674.png)

![](https://raw.githubusercontent.com/Clown95/StroyBack/master/小书匠/1573998272048.png)

## POST路由

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

```

beego.Post("hello2", func(context *context.Context) {

context.WriteString("Hello Beego\n")

})

```

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

![](https://raw.githubusercontent.com/Clown95/StroyBack/master/小书匠/1573998286528.png)

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

![](https://raw.githubusercontent.com/Clown95/StroyBack/master/小书匠/1573998343982.png)

# 固定路由

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

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

# 正则路由

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

先添加路由

```go

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

```

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

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

}

```

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

![](https://raw.githubusercontent.com/Clown95/StroyBack/master/小书匠/1573998361217.png)

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

<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

```go

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

```

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

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

*  `*`表示任意的 method 都执行该函数

*  使用 httpmethod:funcname 格式来展示

*  如果想要使用多个不同的方法使用 `;` 分割

*  多个 method 对应同一个 funcname,method 之间通过 `,` 来分割

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

创建文件 Custom.go

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

```

执行地址;

![](https://raw.githubusercontent.com/Clown95/StroyBack/master/小书匠/1573998450897.png)

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

```go

func (this *CustomController) PostFunc() {

username := this.GetString("username")

password := this.GetString("password")

this.Ctx.WriteString("username = " + username + "\npassword = " + password + "\n用于处理post请求")

}

```

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

```go

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

```

使用PostMan模拟请求

![](https://raw.githubusercontent.com/Clown95/StroyBack/master/小书匠/1573998503676.png)

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

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

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

# 自动匹配

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

```go

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 函数并且参数只有一个控制器。

```go

beego.AutoRouter(&controllers.AutoController{})

```

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

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

`http://localhost:8080/Auto/GetFunc/123/456`

![](https://raw.githubusercontent.com/Clown95/StroyBack/master/小书匠/1573998649411.png)

我们先来简单了解下 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上方写上一定格式的注释,即可注册路由。

注解路由的格式为: 

```go

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

```

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

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

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

```go

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

```

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

```go

beego.Include(&controllers.HelloController{})

```

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

```go

// @router /hello

func (hello * HelloController) Get() {

hello.Ctx.WriteString("hello world\n")

}

```

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

![](https://raw.githubusercontent.com/Clown95/StroyBack/master/小书匠/1573998806310.png)

## URLMapping

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

具体用法如下:

```go

// @router /hello

func (hello * HelloController) Get() {

hello.Ctx.WriteString("hello world\n")

}

func (hello * HelloController) URLMapping() {

hello.Mapping("Get",hello.Get)

}

```

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


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:

查看原文:Beego脱坑(三)Router

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

566 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传