Featured image of post go应用开发框架:beego

go应用开发框架:beego

安装

1
2
$ go get -u github.com/astaxie/beego      //下载beego框架
$ go get -u github.com/beego/bee          //下载bee工具

bee 工具是一个为了协助快速开发 beego 项目而创建的项目,通过 bee 您可以很容易的进行 beego 项目的创建、热编译、开发、测试、和部署。

如果在下载过程中发现很慢,那应该是GOPROXY使用的默认值,下载速度会很慢。可以设置使用以下加速的代理:

国内七牛云代理

1
2
$ go env -w GO111MODULE=on
$ go env -w GOPROXY=https://goproxy.cn,direct

全球CDN加速

1
2
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.io,direct

选择一个就行,下载速度的问题就解决了。当下载完之后,bee的bee.exe便会生成在go的bin目录下和beego框架的源码就被下载到设置了的POPATH执行的目录。如果GOPATH和go的src目录不一致,就把下载好的复制到go的src目录,编写程序时就可以引用了。

bee工具的命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ bee help
Bee is a Fast and Flexible tool for managing your Beego Web Application.

USAGE
    bee command [arguments]

AVAILABLE COMMANDS

    version     Prints the current Bee version
    migrate     Runs database migrations
    api         Creates a Beego API application
    bale        Transforms non-Go files to Go source files
    fix         Fixes your application by making it compatible with newer versions of Beego
    dlv         Start a debugging session using Delve
    dockerize   Generates a Dockerfile for your Beego application
    generate    Source code generator
    hprose      Creates an RPC application based on Hprose and Beego frameworks
    new         Creates a Beego application
    pack        Compresses a Beego application into a single file
    rs          Run customized scripts
    run         Run the application by starting a local development server
    server      serving static content over HTTP on port

Use bee help [command] for more information about a command.

ADDITIONAL HELP TOPICS


Use bee help [topic] for more information about that topic.
bee: Too many arguments.
Use bee help for more information.

bee new创建项目

使用bee工具创建一个web项目,bee new是新建一个web项目。后面接的是想要命名的项目名称。E:\Go\go_project是我自己电脑的GOPATH路径。可见bee新建的项目是存放在GOPATH目录下。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ bee new beedemo
______
| ___ \
| |_/ /  ___   ___
| ___ \ / _ \ / _ \
| |_/ /|  __/|  __/
\____/  \___| \___| v1.10.0
2020/08/22 22:50:04 INFO     ▶ 0001 Creating application...
        create   E:\Go\go_project\src\beedemo\
        create   E:\Go\go_project\src\beedemo\conf\
        create   E:\Go\go_project\src\beedemo\controllers\
        create   E:\Go\go_project\src\beedemo\models\
        create   E:\Go\go_project\src\beedemo\routers\
        create   E:\Go\go_project\src\beedemo\tests\
        create   E:\Go\go_project\src\beedemo\static\
        create   E:\Go\go_project\src\beedemo\static\js\
        create   E:\Go\go_project\src\beedemo\static\css\
        create   E:\Go\go_project\src\beedemo\static\img\
        create   E:\Go\go_project\src\beedemo\views\
        create   E:\Go\go_project\src\beedemo\conf\app.conf
        create   E:\Go\go_project\src\beedemo\controllers\default.go
        create   E:\Go\go_project\src\beedemo\views\index.tpl
        create   E:\Go\go_project\src\beedemo\routers\router.go
        create   E:\Go\go_project\src\beedemo\tests\default_test.go
        create   E:\Go\go_project\src\beedemo\main.go
2020/08/22 22:50:04 SUCCESS  ▶ 0002 New application successfully created!

bee新建的web项目的结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
beedemo
├── conf        //存放配置文件
│   └── app.conf
├── controllers //存放控制器
│   └── default.go
├── main.go    //程序入口
├── models     //存放模型,即与数据库表关联的数据模型
├── routers    //存放路由,通过编写程序将请求路径路由到对应的控制器下的方法就行处理
│   └── router.go
├── static     //存放静态文件,如css文件,图片,js文件
│   ├── css
│   ├── img
│   └── js
├── tests      //测试
│   └── default_test.go
└── views      //视图模板
    └── index.tpl

bee run运行项目

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
E:\Go\go_project\src\beedemo>bee run
______
| ___ \
| |_/ /  ___   ___
| ___ \ / _ \ / _ \
| |_/ /|  __/|  __/
\____/  \___| \___| v1.10.0
2020/08/22 23:44:09 INFO     ▶ 0001 Using 'beedemo' as 'appname'
2020/08/22 23:44:09 INFO     ▶ 0002 Initializing watcher...
2020/08/22 23:44:12 SUCCESS  ▶ 0003 Built Successfully!
2020/08/22 23:44:12 INFO     ▶ 0004 Restarting 'beedemo.exe'...
2020/08/22 23:44:12 SUCCESS  ▶ 0005 './beedemo.exe' is running...
2020/08/22 23:44:12.494 [I] [asm_amd64.s:1357]  http server Running on http://:8080

然后再去访问http://localhost:8080。就可以看到beego的欢迎页了。

如果报错:missing dot in first path element。在项目下执行:go mod init。再去运行项目

beego快速入门

项目路由设置

main.go是整个项目的入口,那么就从main.go开始看

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package main

import (
	_ "beedemo/routers"
	"github.com/astaxie/beego"
)

func main() {
	beego.Run()
}

main函数是入口函数,go的执行流程又如下图所示:

在通过bee生成的main.go文件中,导入了routers包,在routers包下有一个router.go文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package routers

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

func init() {
    beego.Router("/", &controllers.MainController{})
}

init()函数中注册了一个路由:/。路由包里面我们看到执行了路由注册 beego.Router, 这个函数的功能是映射 URL 到 controller,第一个参数是 URL (用户请求的地址),这里我们注册的是 /,也就是我们访问的不带任何参数的 URL,第二个参数是对应的 Controller,也就是我们即将把请求分发到那个控制器来执行相应的逻辑,我们可以执行类似的方式注册如下路由:

1
beego.Router("/index",&controller.IndexController{})

这样用户就可以通过访问 /index 去执行 IndexController 的逻辑。这就是我们所谓的路由,后面会介绍更多更复杂的路由规则。

再回来看看 main 函数里面的 beego.Runbeego.Run 执行之后,我们看到的效果好像只是监听服务端口这个过程,但是它内部做了很多事情:

  • 解析配置文件

    beego 会自动解析在 conf 目录下面的配置文件 app.conf,通过修改配置文件相关的属性,我们可以定义:开启的端口,是否开启 session,应用名称等信息。

  • 执行用户的 hookfunc

    beego 会执行用户注册的 hookfunc,默认的已经存在了注册 mime,用户可以通过函数 AddAPPStartHook 注册自己的启动函数。

  • 是否开启 session

    会根据上面配置文件的分析之后判断是否开启 session,如果开启的话就初始化全局的 session。

  • 是否编译模板

    beego 会在启动的时候根据配置把 views 目录下的所有模板进行预编译,然后存在 map 里面,这样可以有效的提高模板运行的效率,无需进行多次编译。

  • 是否开启文档功能

    根据 EnableDocs 配置判断是否开启内置的文档路由功能

  • 是否启动管理模块

    beego 目前做了一个很酷的模块,应用内监控模块,会在 8088 端口做一个内部监听,我们可以通过这个端口查询到 QPS、CPU、内存、GC、goroutine、thread 等统计信息。

  • 监听服务端口

    这是最后一步也就是我们看到的访问 8080 看到的网页端口,内部其实调用了 ListenAndServe,充分利用了 goroutine 的优势

一旦 run 起来之后,我们的服务就监听在两个端口了,一个服务端口 8080 作为对外服务,另一个 8088 端口实行对内监控。

通过这个代码的分析我们了解了 beego 运行起来的过程,以及内部的一些机制。接下来让我们去剥离 Controller 如何来处理逻辑的。

controller控制器执行逻辑

router.go中又引入了controllers包,下面有一个default.go文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package controllers

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

type MainController struct {
	beego.Controller
}

func (c *MainController) Get() {
	c.Data["Website"] = "beego.me"
	c.Data["Email"] = "astaxie@gmail.com"
	c.TplName = "index.tpl"
}

上面的代码显示首先声明了一个控制器 MainController,这个控制器里面内嵌了 beego.Controller,这就是 Go 的嵌入方式,也就是 MainController 自动拥有了所有 beego.Controller 的方法。

beego.Controller 拥有很多方法,其中包括 InitPreparePostGetDeleteHead 等方法。也可以通过重写的方式来实现这些方法,上面的代码就是重写了 Get 方法。

beego 是一个 RESTful 的框架,所以的请求默认是执行对应 req.Method 的方法。例如浏览器的是 GET 请求,那么默认就会执行 MainController 下的 Get 方法。这样上面的 Get 方法就会被执行到,这样就进入了逻辑处理。(后续将介绍自定义路由规则)里面的代码是需要执行的逻辑,这里只是简单的输出数据,可以通过各种方式获取数据,然后赋值到 this.Data 中,这是一个用来存储输出数据的 map,可以赋值任意类型的值,这里只是简单举例输出两个字符串。

最后一个就是需要去渲染的模板,this.TplName 就是需要渲染的模板,这里指定了 index.tpl,如果用户不设置该参数,那么默认会去到模板目录的 Controller/<方法名>.tpl 查找,例如上面的方法会去 maincontroller/get.tpl (文件、文件夹必须小写。beego框架规定的)

用户设置了模板之后系统会自动的调用 Render 函数(这个函数是在 beego.Controller 中实现的),所以无需用户自己来调用渲染。

当然也可以不使用模版,直接用 this.Ctx.WriteString 输出字符串,如:

1
2
3
func (this *MainController) Get() {
	this.Ctx.WriteString("hello")
}

至此控制器分析基本完成了,接下来看一看如何来编写 model。

model分析

Web 应用中用的最多的就是数据库操作,而 model 层一般用来做这些操作, bee new 例子不存在 Model 的演示,但是 bee api 应用中存在 model 的应用。其实如果一个应用足够简单,那么 Controller 可以处理一切的逻辑,如果逻辑里面存在着可以复用的东西,那么就抽取出来变成一个模块。因此 Model 就是逐步抽象的过程,一般会在 Model 里面处理一些数据读取,如下是一个日志分析应用中的代码片段:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package models

import (
    "loggo/utils"
    "path/filepath"
    "strconv"
    "strings"
)

var (
    NotPV []string = []string{"css", "js", "class", "gif", "jpg", "jpeg", "png", "bmp", "ico", "rss", "xml", "swf"}
)

const big = 0xFFFFFF

func LogPV(urls string) bool {
    ext := filepath.Ext(urls)
    if ext == "" {
        return true
    }
    for _, v := range NotPV {
        if v == strings.ToLower(ext) {
            return false
        }
    }
    return true
}

所以应用足够简单,那么就不需要 Model 了;如果模块开始多了,需要复用,需要逻辑分离了,那么 Model 是必不可少的。接下来分析如何编写 View 层的东西。

View层的编写

在前面编写 Controller 的时候,在MainController中的 Get方法 里面写过这样的语句 this.TplName = "index.tpl",设置显示的模板文件,默认支持 tplhtml 的后缀名,如果想设置其他后缀可以调用 beego.AddTemplateExt 接口设置,那么模板如何来显示相应的数据呢?beego 采用了 Go 语言默认的模板引擎,所以和 Go 的模板语法一样,Go 模板的详细使用方法请参考《Go Web 编程》模板使用指南

在快速入门中beegodemo中创建的index.tpl里面的代码(去掉了 css 样式):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html>
    <head>
        <title>Beego</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>
        <header class="hero-unit" style="background-color:#A9F16C">
            <div class="container">
                <div class="row">
                    <div class="hero-text">
                        <h1>Welcome to Beego!</h1>
                        <p class="description">
                            Beego is a simple & powerful Go web framework which is inspired by tornado and sinatra.
                            <br />
                            Official website: <a href="http://{{.Website}}">{{.Website}}</a>
                            <br />
                            Contact me: {{.Email}}
                        </p>
                    </div>
                </div>
            </div>
        </header>
    </body>
</html>

在 Controller 里面把数据赋值给了 data(map 类型),然后我们在模板中就直接通过 key 访问 .Website.Email 。这样就做到了数据的输出。接下来讲解如何让静态文件输出。

静态文件处理

前面介绍了如何输出静态页面,但是一个网页往往包含了很多的静态文件,包括图片、JS、CSS 等,bee工具创建的应用里面就创建了如下目录:

1
2
3
4
├── static
    │   ├── css
    │   ├── img
    │   └── js

beego 默认注册了 static 目录为静态处理的目录,注册样式:URL 前缀和映射的目录(在/main.go文件中beego.Run()之前加入):

1
StaticDir["/static"] = "static"

用户可以设置多个静态文件处理目录,例如你有多个文件下载目录 download1、download2,你可以这样映射(在 /main.go 文件中 beego.Run() 之前加入)。

例如:在static文件夹下新建download1和download2文件夹,并分别在这两个文件夹下创建文件123.txt和345.txt。里面的内容分别是"123"和345,在代码中注册静态文件夹和匹配的路径

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

import (
	_ "beedemo/routers"
	"github.com/astaxie/beego"
)

func main() {
	beego.SetStaticPath("/down1","static/download1")
	beego.SetStaticPath("/down2","static/download2")
	beego.Run()
}

这样访问 URL http://localhost:8080/down1/123.txt 则会请求 download1 目录下的 123.txt 文件。在浏览器上就会显示文件里面的内容。

beego的MVC架构设计

执行逻辑图

执行流程分析

  1. 在监听的端口接收数据,默认监听在 8080 端口。
  2. 用户请求到达 8080 端口之后进入 beego 的处理逻辑。
  3. 初始化 Context 对象,根据请求判断是否为 WebSocket 请求,如果是的话设置 Input,同时判断请求的方法是否在标准请求方法中(GET、POST、PUT、DELETE、PATCH、OPTIONS、HEAD),防止用户的恶意伪造请求攻击造成不必要的影响。
  4. 执行 BeforeRouter 过滤器,当然在 beego 里面有开关设置。如果用户设置了过滤器,那么该开关打开,这样可以提高在没有开启过滤器的情况下提高执行效率。如果在执行过滤器过程中,responseWriter已经有数据输出了,那么就提前结束该请求,直接跳转到监控判断。
  5. 开始执行静态文件的处理,查看用户的请求 URL 是否和注册在静态文件处理 StaticDir 中的 prefix 是否匹配。如果匹配的话,采用 http 包中默认的 ServeFile 来处理静态文件。
  6. 如果不是静态文件开始初始化 session 模块(如果开启 session 的话),这个里面大家需要注意,如果你的 BeforeRouter 过滤器用到了 session 就会报错,你应该把它加入到 AfterStatic 过滤器中。
  7. 开始执行 AfterStatic 过滤器,如果在执行过滤器过程中,responseWriter 已经有数据输出了,那么就提前结束该请求,直接跳转到监控判断。
  8. 执行过过滤器之后,开始从固定的路由规则中查找和请求 URL 相匹配的对象。这个匹配是全匹配规则,即如果用户请求的 URL 是 /hello/world,那么固定规则中 /hello 是不会匹配的,只有完全匹配才算匹配。如果匹配的话就进入逻辑执行,如果不匹配进入下一环节的正则匹配。
  9. 正则匹配是进行正则的全匹配,这个正则是按照用户添加 beego 路由顺序来进行匹配的,也就是说,如果你在添加路由的时候你的顺序影响你的匹配。和固定匹配一样,如果匹配的话就进行逻辑执行,如果不匹配进入 Auto 匹配。
  10. 如果用户注册了 AutoRouter,那么会通过 controller/method 这样的方式去查找对应的 Controller 和他内置的方法,如果找到就开始执行逻辑,如果找不到就跳转到监控判断。
  11. 如果找到 Controller 的话,那么就开始执行逻辑,首先执行 BeforeExec 过滤器,如果在执行过滤器过程中,responseWriter 已经有数据输出了,那么就提前结束该请求,直接跳转到监控判断。
  12. Controller 开始执行 Init 函数,初始化基本的一些信息,这个函数一般都是 beego.Controller 的初始化,不建议用户继承的时候修改该函数。
  13. 是否开启了 XSRF,开启的话就调用 Controller 的 XsrfToken,然后如果是 POST 请求就调用 CheckXsrfCookie 方法。
  14. 继续执行 Controller 的 Prepare 函数,这个函数一般是预留给用户的,用来做 Controller 里面的一些参数初始化之类的工作。如果在初始化中 responseWriter 有输出,那么就直接进入 Finish 函数逻辑。
  15. 如果没有输出的话,那么根据用户注册的方法执行相应的逻辑,如果用户没有注册,那么就调用 http.Method 对应的方法(Get/Post 等)。执行相应的逻辑,例如数据读取,数据赋值,模板显示之类的,或者直接输出 JSON 或者 XML。
  16. 如果 responseWriter 没有输出,那么就调用 Render 函数进行模板输出。
  17. 执行 Controller 的 Finish 函数,这个函数是预留给用户用来重写的,用于释放一些资源。释放在 Init 中初始化的信息数据。
  18. 执行 AfterExec 过滤器,如果有输出的话就跳转到监控判断逻辑。
  19. 执行 Controller 的 Destructor,用于释放 Init 中初始化的一些数据。
  20. 如果这一路执行下来都没有找到路由,那么会调用 404 显示找不到该页面。
  21. 最后所有的逻辑都汇聚到了监控判断,如果用户开启了监控模块(默认是开启一个 8088 端口用于进程内监控),这样就会把访问的请求链接扔给监控程序去记录当前访问的 QPS,对应的链接访问的执行时间,请求链接等。

接下来就让我们开始进入 beego 的 MVC 核心第一步,路由设置:

路由设置

beego 存在三种方式的路由:固定路由、正则路由、自动路由,接下来详细的讲解如何使用这三种路由。

基础路由

从 beego 1.2 版本开始支持了基本的 RESTful 函数式路由,应用中的大多数路由都会定义在 routers/router.go 文件中。最简单的 beego 路由由 URI 和闭包函数组成。

  1. 基础路由Get,Post。通过postman用对应的HTTP请求去访问:http://localhost:8080/basic/get,http://localhost:8080/basic/get

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    package routers
    
    import (
    	"github.com/astaxie/beego"
    	"github.com/astaxie/beego/context"
    )
    func init() {
    	// 1.基础路由
    	beego.Get("/basic/get",func(ctx *context.Context){
    		ctx.Output.Body([]byte("basic router get"))
    	})
    	beego.Post("/basic/post",func(ctx *context.Context){
    		ctx.Output.Body([]byte("basic router post"))
    	})
    }
    
  2. 注册一个可以响应任何 HTTP 的路由

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    package routers
    
    import (
    	"github.com/astaxie/beego"
    	"github.com/astaxie/beego/context"
    )
    
    func init() {
    	// 1.基础路由
    	beego.Get("/basic/get",func(ctx *context.Context){
    		ctx.Output.Body([]byte("basic router get"))
    	})
    	beego.Post("/basic/post",func(ctx *context.Context){
    		ctx.Output.Body([]byte("basic router post"))
    	})
    	// 2.注册一个可以响应任意HTTP请求的路由
    	beego.Any("/basic/any",func(ctx *context.Context){
    		ctx.Output.Body([]byte("basic router any"))
    	})
    }
    
  3. beego所支持的基础函数如下

  • beego.Get(router, beego.FilterFunc)
  • beego.Post(router, beego.FilterFunc)
  • beego.Put(router, beego.FilterFunc)
  • beego.Patch(router, beego.FilterFunc)
  • beego.Head(router, beego.FilterFunc)
  • beego.Options(router, beego.FilterFunc)
  • beego.Delete(router, beego.FilterFunc)
  • beego.Any(router, beego.FilterFunc)
  1. 自定义handler

    有些时候项目中已经实现了一些 rpc 的应用,但是想要集成到 beego 中,或者其他的 httpserver 应用,集成到 beego 中来.现在可以很方便的集成

    1
    2
    3
    4
    
    s := rpc.NewServer()
    s.RegisterCodec(json.NewCodec(), "application/json")
    s.RegisterService(new(HelloService), "")
    beego.Handler("/rpc", s)
    

    beego.Handler(router, http.Handler) 这个函数是关键,第一个参数表示路由 URI, 第二个就是你自己实现的 http.Handler, 注册之后就会把所有 rpc 作为前缀的请求分发到 http.Handler 中进行处理.

    这个函数其实还有第三个参数就是是否是前缀匹配,默认是 false, 如果设置了 true, 那么就会在路由匹配的时候前缀匹配,即 /rpc/user 这样的也会匹配去运行

  2. 路由参数

    在项目开发中通常是需要在请求中获取对应的参数,后面的固定路由,正则路由,这些参数一样适用于上面的这些函数

RESTful Controller 路由

RESTful 是一种目前 API 开发中广泛采用的形式,beego 默认就是支持这样的请求方法,也就是用户 Get 请求就执行 Get 方法,Post 请求就执行 Post 方法。因此默认的路由是这样 RESTful 的请求方式。

RESTful风格的固定路由

固定路由也就是全匹配的路由.

controllers包下创建UserController、ArticleController和AddController.

UserController.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package controllers

import "github.com/astaxie/beego"

type UserController struct {
	beego.Controller
}

func (c *UserController) Get() {
	c.Ctx.Output.Body([]byte("path:/admin UserController:Get"))
}

ArticleController.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package controllers

import "github.com/astaxie/beego"

type ArticleController struct {
	beego.Controller
}

func (c *ArticleController) Get() {
	c.Ctx.Output.Body([]byte("path:/admin/addpkg ArticleController:Get"))
}

AddController.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package controllers

import "github.com/astaxie/beego"

type AddController struct {
	beego.Controller
}

func (c *AddController) Get() {
	c.Ctx.Output.Body([]byte("path:/admin/index AddController:Get"))
}

编写完之后去路由进行注册,如下面所示的路由就是我们最常用的路由方式,一个固定的路由,一个控制器,然后根据用户请求方法不同请求控制器中对应的方法,典型的 RESTful 方式。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package routers

import (
	"beedemo/controllers"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/context"
)

func init() {
	// RESTful固定路由
	beego.Router("/", &controllers.MainController{})
	beego.Router("/admin", &controllers.UserController{})
	beego.Router("/admin/index", &controllers.ArticleController{})
	beego.Router("/admin/addpkg", &controllers.AddController{})
}

正则路由

为了用户更加方便的路由设置,beego 参考了 sinatra 的路由实现,支持多种方式的路由:

  • beego.Router("/api/?:id", &controllers.RController{})

    默认匹配 //例如对于URL"/api/123"可以匹配成功,此时变量":id"值为"123"

  • beego.Router("/api/:id", &controllers.RController{})

    默认匹配 //例如对于URL"/api/123"可以匹配成功,此时变量":id"值为"123",但URL"/api/“匹配失败

  • beego.Router("/api/:id([0-9]+)" &controllers.RController{})

    自定义正则匹配 //例如对于URL"/api/123"可以匹配成功,此时变量":id"值为"123"

  • beego.Router("/user/:username([\w]+)", &controllers.RController{})

    正则字符串匹配 //例如对于URL"/user/astaxie"可以匹配成功,此时变量":username"值为"astaxie"

  • beego.Router("/download/.", &controllers.RController{})

    *匹配方式 //例如对于URL"/download/file/api.xml"可以匹配成功,此时变量":path"值为"file/api", “:ext"值为"xml"

  • beego.Router("/download/ceshi/*", &controllers.RController{})

    *全匹配方式 //例如对于URL"/download/ceshi/file/api.json"可以匹配成功,此时变量":splat"值为"file/api.json"

  • beego.Router("/:id :int", &controllers.RController{})

    int 类型设置方式,匹配 :id为int 类型,框架帮你实现了正则 ([0-9]+)

  • beego.Router("/:hi:string", &controllers.RController{})

    string 类型设置方式,匹配 :hi 为 string 类型。框架帮你实现了正则 ([\w]+)

  • beego.Router("/cms_:id([0-9]+).html", &controllers.CmsController{})

    带有前缀的自定义正则 //匹配 :id 为正则类型。匹配 cms_123.html 这样的 url :id = 123

现在在controllers包下创建RController

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
type RController struct {
	beego.Controller
}

func (c *RController) Get() {
    // 获取参数
	id := c.Ctx.Input.Param(":id")
    // 再响应回去
	c.Ctx.Output.Body([]byte("path param"+id))
}

router.go中注册正则路由

1
beego.Router("/api/?:id", &controllers.RController{})

postman访问http://localhost:8080/api/123,会返回"path parma123"。说明路由匹配成功。当访问http://localhost:8080/api的时候路由也会匹配成功,页面返回了"path param",就是参数为空。

现在把路由的匹配换成一下进行注册,然后再分别请求访问http://localhost:8080/api/123和http://localhost:8080/api。前者会匹配成功,页面返回了"path param123"。后者会出现404页面,路由匹配失败。

1
beego.Router("/api/:id", &controllers.RController{})

“/api/:id([0-9]+)“和”/user/:username([\w]+)",其实从正则表达式就可以看得出来,前者是只匹配数字,后者只匹配字符。修改UserController

1
2
3
4
5
func (c *UserController) Get() {
	username := c.Ctx.Input.Param(":username")
	//c.Ctx.Output.Body([]byte("path:/admin UserController:Get"))
	c.Ctx.Output.Body([]byte("path param username:" + username))
}

注册路由

1
2
beego.Router("/api/:id([0-9]+)", &controllers.RController{})
beego.Router("/user/:username([\\w]+)", &controllers.UserController{})

访问测试http://localhost:8080/api/123和http://localhost:8080/api/kkk。前者会匹配成功,页面返回"path param id:123” ,后者访问会404。http://localhost:8080/user/123和http://localhost:8080/user/kkk。这两个路径都会成功匹配并路由到UserController的Get方法。

控制器函数

xsrf 过滤

session 控制

flash 数据

请求数据处理

多种格式数据输出

表单数据验证

模板输出

模板函数

错误处理

静态文件处理

参数配置

日志处理

TODO更新中…