1 Star 1 Fork 25

2733284198 / gfstudy

forked from goflyfox / gfstudy 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
04.goframe路由注册.md 8.79 KB
一键复制 编辑 原始数据 按行查看 历史
zcool321@sina.com 提交于 2020-03-22 21:06 . update router example

GoFrame路由注册

一、路由规则

gf框架自建了非常强大的路由功能,提供了比任何同类框架更加出色的路由特性,支持流行的命名匹配规则、模糊匹配规则及字段匹配规则,并提供了优秀的优先级管理机制。

该方法是路由注册的最基础方法,其中的pattern为路由注册规则字符串,在其他路由注册方法中也会使用到,参数格式如下:

[HTTPMethod:]路由规则[@域名]

其中HTTPMethod(支持的Method:GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE)和@域名为非必需参数,一般来说直接给定路由规则参数即可,BindHandler会自动绑定所有的请求方式,如果给定HTTPMethod,那么路由规则仅会在该请求方式下有效。@域名可以指定生效的域名名称,那么该路由规则仅会在该域名下生效。

BindHandler是最原生的路由注册方法,在大部分场景中,我们通常使用 分组路由 方式来管理路由

示例:

	// hello方法,post调用
	s.BindHandler("POST:/hello", func(r *ghttp.Request) {
		r.Response.Writeln("url" + r.Router.Uri)
	})

二、回调函数注册

回调函数注册方式是最简单且最灵活的的路由注册方式,注册的服务可以是一个实例化对象的方法地址,也可以是一个包方法地址。服务需要的数据可以通过模块内部变量形式或者对象内部变量形式进行管理,开发者可根据实际情况进行灵活控制。

我们可以直接通过BindHandler方法完成回调函数的注册,在框架的开发手册中很多地方都使用了回调函数注册的方式来做演示,因为这种注册方式比较简单。

示例:

	// 方法注册
	s.BindHandler("/total", Total)

三、执行对象注册

执行对象注册是在注册时便给定一个实例化的对象,以后每一个请求都交给该对象(同一对象)处理,该对象常驻内存不释放。服务端进程在启动时便需要初始化这些执行对象,并且这些对象需要自行负责对自身数据的并发安全维护(往往对象的成员变量应当是并发安全的,每个请求执行完毕后该对象不会销毁,其成员变量也不会释放)。

	// 对象注册
	c := new(Controller)
	s.BindObject("POST:/object", c)

四、分组注册

GF框架支持分组路由的注册方式,可以给分组路由指定一个prefix前缀(也可以直接给定/前缀,表示注册在根路由下),在该分组下的所有路由注册都将注册在该路由前缀下。分组路由注册方式也是推荐的路由注册方式。

示例:

    // 分组注册及中间件
	group := s.Group("/api")
	group.ALL("/all", func(r *ghttp.Request) {
		r.Response.Writeln("all")
	})

五、中间件设计

GF提供了优雅的中间件请求控制方式,该方式也是主流的WebServer提供的请求流程控制方式,基于中间件设计可以为WebServer提供更灵活强大的插件机制。经典的中间件洋葱模型:

经典的中间件洋葱模型

示例:

    // 分组注册及中间件
	group := s.Group("/api")
	group.Middleware(MiddlewareTest)
	group.ALL("/all", func(r *ghttp.Request) {
		r.Response.Writeln("all")
	})

六、请求和响应对象

请求Request

请求输入依靠 ghttp.Request 对象实现,ghttp.Request继承了底层的http.Request对象。ghttp.Request包含一个与当前请求对应的返回输出对象Response,用于数据的返回处理。

可以看到Request对象的参数获取方法非常丰富,可以分为以下几类:

  1. Get*: 常用方法,简化参数获取,GetRequest*的别名。
  2. GetQuery*: 获取GET方式传递过来的参数,包括Query StringBody参数解析。
  3. GetForm*: 获取表单方式传递过来的参数,表单方式提交的参数Content-Type往往为application/x-www-form-urlencoded, application/form-data, multipart/form-data, multipart/mixed等等。
  4. GetRequest*: 获取客户端提交的参数,不区分提交方式。
  5. Get*Struct: 将指定类型的请求参数绑定到指定的struct对象上,注意给定的参数为对象指针。绝大部分场景中往往使用Parse方法将请求数据转换为请求对象,具体详见后续章节。
  6. GetBody/GetBodyString: 获取客户端提交的原始数据,该数据是客户端写入到body中的原始数据,与HTTP Method无关,例如客户端提交JSON/XML数据格式时可以通过该方法获取原始的提交数据。
  7. GetJson: 自动将原始请求信息解析为gjson.Json对象指针返回。
  8. Exit*: 用于请求流程退出控制;

响应Response

ghttp.Response对象实现了标准库的http.ResponseWriter接口。数据输出使用Write*相关方法实现,并且数据输出采用了Buffer机制,因此数据的处理效率比较高。任何时候可以通过OutputBuffer方法输出缓冲区数据到客户端,并清空缓冲区数据。

简要说明:

  1. Write*方法用于数据的输出,可为任意的数据格式,内部通过断言对参数做自动分析。
  2. Write*Exit方法用于数据输出后退出当前服务方法,可用于替代return返回方法。
  3. WriteJson*/WriteXml方法用于特定数据格式的输出,这是为开发者提供的简便方法。
  4. WriteTpl*方法用于模板输出,解析并输出模板文件,也可以直接解析并输出给定的模板内容。
  5. ParseTpl*方法用于模板解析,解析模板文件或者模板内容,返回解析后的内容。

七、教程示例

package main

import (
	"github.com/gogf/gf/container/gtype"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
)

func main() {
	s := g.Server()
	// 常规注册
	// hello方法,post调用
	s.BindHandler("POST:/hello", func(r *ghttp.Request) {
		r.Response.Writeln("url" + r.Router.Uri)
	})
	// 所有方法,url包含name参数
	s.BindHandler("/:name", func(r *ghttp.Request) {
		// 获取URL name参数
		r.Response.Writeln("name:" + r.GetString("name"))
		r.Response.Writeln("url" + r.Router.Uri)
	})
	// 所有方法,url包含name参数
	s.BindHandler("/:name/update", func(r *ghttp.Request) {
		r.Response.Writeln("name:" + r.GetString("name"))
		r.Response.Writeln("url" + r.Router.Uri)
	})
	// 所有方法,url包含name和action参数
	s.BindHandler("/:name/:action", func(r *ghttp.Request) {
		r.Response.Writeln("name:" + r.GetString("name"))
		r.Response.Writeln("action:" + r.GetString("action"))
		r.Response.Writeln("url" + r.Router.Uri)
	})
	// 所有方法,url包含field属性
	s.BindHandler("/user/list/{field}.html", func(r *ghttp.Request) {
		// 获取URL field属性
		r.Response.Writeln("field:" + r.GetString("field"))
		r.Response.Writeln("url" + r.Router.Uri)
	})

	// 方法注册
	s.BindHandler("/total", Total)

	// 对象注册
	c := new(Controller)
	s.BindObject("POST:/object", c)


	// 分组注册及中间件
	group := s.Group("/api")
	group.Middleware(MiddlewareTest)
	group.ALL("/all", func(r *ghttp.Request) {
		r.Response.Writeln("all")
	})
	group.GET("/get", func(r *ghttp.Request) {
		r.Response.Writeln("get")
	})
	group.POST("/post", func(r *ghttp.Request) {
		r.Response.Writeln("post")
	})

	// request and response
	s.BindHandler("POST:/test", func(r *ghttp.Request) {
		r.Response.WriteJson(g.Map{
			"name":r.GetString("name"),
			"age":r.GetInt("age"),
			"sex":r.Header.Get("sex"),
		})
	})

	s.SetPort(8199)
	s.Run()
}

var (
	total = gtype.NewInt()
)

func Total(r *ghttp.Request) {
	r.Response.Write("total:", total.Add(1))
}

// 对象注册
type Controller struct{}

func (c *Controller) Index(r *ghttp.Request) {
	r.Response.Write("index")
}

func (c *Controller) Show(r *ghttp.Request) {
	r.Response.Write("show")
}

// 中间件
func MiddlewareTest(r *ghttp.Request) {
	// 前置逻辑
	r.Response.Writeln("###start")
	r.Middleware.Next()
	// 后置逻辑
	r.Response.Writeln("###end")
}

访问结果:

### 常规注册
POST http://localhost:8199/hello

###
GET http://localhost:8199/abc

###
GET http://localhost:8199/a/add

###
GET http://localhost:8199/a/update

###
GET http://localhost:8199/user/list/11.html

### 方法注册
GET http://localhost:8199/total

### 对象注册默认访问index
POST http://localhost:8199/object/

### 对象注册直接访问Index
POST http://localhost:8199/object/index

### 对象注册访问show方法
POST http://localhost:8199/object/show

### 分组默认访问index
PUT http://localhost:8199/api/all

### 对象注册直接访问Index
GET http://localhost:8199/api/get

### 对象注册访问show方法
POST http://localhost:8199/api/post

### request and response
POST http://localhost:8199/test
sex:man

name=liubang&age=18

###
1
https://gitee.com/linlin2018/gfstudy.git
git@gitee.com:linlin2018/gfstudy.git
linlin2018
gfstudy
gfstudy
master

搜索帮助