新聞中心
?GOframe?框架自建了非常強(qiáng)大的路由功能,提供了比任何同類(lèi)框架更加出色的路由特性,支持流行的命名匹配規(guī)則、模糊匹配規(guī)則及字段匹配規(guī)則,并提供了優(yōu)秀的優(yōu)先級(jí)管理機(jī)制。

公司主營(yíng)業(yè)務(wù):網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來(lái)驚喜。創(chuàng)新互聯(lián)推出三河免費(fèi)做網(wǎng)站回饋大家。
一個(gè)示例
在真正開(kāi)啟本章的核心內(nèi)容之前,我們先來(lái)看一個(gè)簡(jiǎn)單的動(dòng)態(tài)路由使用示例:
package main
import (
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/frame/g"
)
func main() {
s := g.Server()
s.BindHandler("/:name", func(r *ghttp.Request){
r.Response.Writeln(r.Router.Uri)
})
s.BindHandler("/:name/update", func(r *ghttp.Request){
r.Response.Writeln(r.Router.Uri)
})
s.BindHandler("/:name/:action", func(r *ghttp.Request){
r.Response.Writeln(r.Router.Uri)
})
s.BindHandler("/:name/*any", func(r *ghttp.Request){
r.Response.Writeln(r.Router.Uri)
})
s.BindHandler("/user/list/{field}.html", func(r *ghttp.Request){
r.Response.Writeln(r.Router.Uri)
})
s.SetPort(8199)
s.Run()
}以上示例中展示了?GoFrame?框架支持的三種模糊匹配路由規(guī)則,?:name?、?*any?、?{field}?分別表示命名匹配規(guī)則、模糊匹配規(guī)則及字段匹配規(guī)則。不同的規(guī)則中使用?/?符號(hào)來(lái)劃分層級(jí),路由檢索采用深度優(yōu)先算法,層級(jí)越深的規(guī)則優(yōu)先級(jí)也會(huì)越高。我們運(yùn)行以上示例,通過(guò)訪問(wèn)幾個(gè)URL來(lái)看看效果:
URL 結(jié)果
http://127.0.0.1:8199/user/list/2.html /user/list/{field}.html
http://127.0.0.1:8199/user/update /:name/update
http://127.0.0.1:8199/user/info /:name/:action
http://127.0.0.1:8199/user /:name/*any在這個(gè)示例中我們也可以看到,由于優(yōu)先級(jí)的限制,路由規(guī)則?/:name?會(huì)被?/:name/*any?規(guī)則覆蓋,將會(huì)無(wú)法被匹配到,所以在分配路由規(guī)則的時(shí)候,需要進(jìn)行統(tǒng)一規(guī)劃和管理,避免類(lèi)似情況的產(chǎn)生。
注冊(cè)規(guī)則
路由注冊(cè)參數(shù)
我們來(lái)看一下之前一直使用的?BindHandler?的原型:
func (s *Server) BindHandler(pattern string, handler interface{})該方法是路由注冊(cè)的最基礎(chǔ)方法,其中的?pattern?為路由注冊(cè)規(guī)則字符串,在其他路由注冊(cè)方法中也會(huì)使用到,參數(shù)格式如下:
[HTTPMethod:]路由規(guī)則[@域名]其中?HTTPMethod?(支持的Method:?GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE?)和?@域名?為非必需參數(shù),一般來(lái)說(shuō)直接給定路由規(guī)則參數(shù)即可,?BindHandler?會(huì)自動(dòng)綁定所有的請(qǐng)求方式,如果給定?HTTPMethod?,那么路由規(guī)則僅會(huì)在該請(qǐng)求方式下有效。?@域名?可以指定生效的域名名稱,那么該路由規(guī)則僅會(huì)在該域名下生效。
?BindHandler?是最原生的路由注冊(cè)方法,在大部分場(chǎng)景中,我們通常使用分組路由方式來(lái)管理理由。
我們來(lái)看一個(gè)例子:
package main
import (
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/frame/g"
)
func main() {
s := g.Server()
// 該路由規(guī)則僅會(huì)在GET請(qǐng)求下有效
s.BindHandler("GET:/{table}/list/{page}.html", func(r *ghttp.Request){
r.Response.WriteJson(r.Router)
})
// 該路由規(guī)則僅會(huì)在GET請(qǐng)求及l(fā)ocalhost域名下有效
s.BindHandler("GET:/order/info/{order_id}@localhost", func(r *ghttp.Request){
r.Response.WriteJson(r.Router)
})
// 該路由規(guī)則僅會(huì)在DELETE請(qǐng)求下有效
s.BindHandler("DELETE:/comment/{id}", func(r *ghttp.Request){
r.Response.WriteJson(r.Router)
})
s.SetPort(8199)
s.Run()
}其中返回的參數(shù)?r.Router?是當(dāng)前匹配的路由規(guī)則信息,訪問(wèn)當(dāng)該方法的時(shí)候,服務(wù)端會(huì)輸出當(dāng)前匹配的路由規(guī)則信息。執(zhí)行后,我們?cè)诮K端使用?curl?命令進(jìn)行測(cè)試:
$ curl -XGET http://127.0.0.1:8199/order/list/1.html
{"Domain":"default","Method":"GET","Priority":3,"Uri":"/{table}/list/{page}.html"}
$ curl -XGET http://127.0.0.1:8199/order/info/1
Not Found
$ curl -XGET http://localhost:8199/order/info/1
{"Domain":"localhost","Method":"GET","Priority":3,"Uri":"/order/info/{order_id}"}
$ curl -XDELETE http://127.0.0.1:8199/comment/1000
{"Domain":"default","Method":"DELETE","Priority":2,"Uri":"/comment/{id}"}
$ curl -XGET http://127.0.0.1:8199/comment/1000
Not Found值得說(shuō)明的是,在大多數(shù)場(chǎng)景下,我們很少直接在路由規(guī)則中使用?@域名?這樣的規(guī)則來(lái)限定路由注冊(cè)的域名,而是使用?ghttp.Server.Domain(domains string)?方法來(lái)獲得指定域名列表的管理對(duì)象,隨后使用該域名對(duì)象進(jìn)行路由注冊(cè),域名對(duì)象即可實(shí)現(xiàn)對(duì)指定域名的綁定操作。
精準(zhǔn)匹配規(guī)則
精準(zhǔn)匹配規(guī)則即未使用任何動(dòng)態(tài)規(guī)則的規(guī)則,如:?user?、?order?、?info?等等這種確定名稱的規(guī)則。在大多數(shù)場(chǎng)景下,精準(zhǔn)匹配規(guī)則會(huì)和動(dòng)態(tài)規(guī)則一起使用來(lái)進(jìn)行路由注冊(cè)(例如:?/:name/list?,其中層級(jí)1?:name?為命名匹配規(guī)則,層級(jí)2?list?是精準(zhǔn)匹配規(guī)則)。
動(dòng)態(tài)路由規(guī)則
動(dòng)態(tài)路由規(guī)則分為三種:命名匹配規(guī)則、模糊匹配規(guī)則和字段匹配規(guī)則。動(dòng)態(tài)路由的底層數(shù)據(jù)結(jié)構(gòu)是由層級(jí)哈希表和雙向鏈表構(gòu)建的路由樹(shù),層級(jí)哈希表便于高效率地層級(jí)匹配?URI?;數(shù)據(jù)鏈表用于優(yōu)先級(jí)控制,同一層級(jí)的路由規(guī)則按照優(yōu)先級(jí)進(jìn)行排序,優(yōu)先級(jí)高的規(guī)則排在鏈表頭。底層的路由規(guī)則與請(qǐng)求?URI?的匹配計(jì)算采用的是正則表達(dá)式,并充分使用了緩存機(jī)制,執(zhí)行效率十分高效。
所有匹配到的參數(shù)都將會(huì)以?Router?參數(shù)的形式傳遞給業(yè)務(wù)層,可以通過(guò)?ghttp.Request?對(duì)象的以下方法獲?。?/p>
func (r *Request) GetRouterValue(key string, def ...interface{}) interface{}
func (r *Request) GetRouterVar(key string, def ...interface{}) *gvar.Var
func (r *Request) GetRouterString(key string, def ...interface{}) string也可以使用?ghttp.Request.Get*?方式進(jìn)行獲取。
命名匹配規(guī)則
使用?:name?方式進(jìn)行匹配(?name?為自定義的匹配名稱),對(duì)?URI?指定層級(jí)的參數(shù)進(jìn)行命名匹配(類(lèi)似正則([^/]+),該URI層級(jí)必須有值),對(duì)應(yīng)匹配參數(shù)會(huì)被解析為Router參數(shù)并傳遞給注冊(cè)的服務(wù)接口使用。
匹配示例1:
rule: /user/:user
/user/john match
/user/you match
/user/john/profile no match
/user/ no match匹配示例2:
rule: /:name/action
/john/name no match
/john/action match
/smith/info no match
/smith/info/age no match
/smith/action match匹配示例3:
rule: /:name/:action
/john/name match
/john/info match
/smith/info match
/smith/info/age no match
/smith/action/del no match
模糊匹配規(guī)則
使用?*any?方式進(jìn)行匹配(?any?為自定義的匹配名稱),對(duì)?URI?指定位置之后的參數(shù)進(jìn)行模糊匹配(類(lèi)似正則?(.*)?,該?URI?層級(jí)可以為空),并將匹配參數(shù)解析為?Router?參數(shù)并傳遞給注冊(cè)的服務(wù)接口使用。
匹配示例1:
rule: /src/*path
/src/ match
/src/somefile.go match
/src/subdir/somefile.go match
/user/ no match
/user/john no match匹配示例2:
rule: /src/*path/:action
/src/ no match
/src/somefile.go match
/src/somefile.go/del match
/src/subdir/file.go/del match匹配示例3:
rule: /src/*path/show
/src/ no match
/src/somefile.go no match
/src/somefile.go/del no match
/src/somefile.go/show match
/src/subdir/file.go/show match
/src/show match
字段匹配規(guī)則
使用?{field}?方式進(jìn)行匹配(?field?為自定義的匹配名稱),可對(duì)?URI?任意位置的參數(shù)進(jìn)行截取匹配(類(lèi)似正則?([\w\.\-]+)?,該?URI?層級(jí)必須有值,并且可以在同一層級(jí)進(jìn)行多個(gè)字段匹配),并將匹配參數(shù)解析為?Router?參數(shù)并傳遞給注冊(cè)的服務(wù)接口使用。
匹配示例1:
rule: /order/list/{page}.php
/order/list/1.php match
/order/list/666.php match
/order/list/2.php5 no match
/order/list/1 no match
/order/list no match匹配示例2:
rule: /db-{table}/{id}
/db-user/1 match
/db-user/2 match
/db/user/1 no match
/db-order/100 match
/database-order/100 no match匹配示例3:
rule: /{obj}-{act}/*param
/user-delete/10 match
/order-update/20 match
/log-list match
/log/list/1 no match
/comment/delete/10 no match
動(dòng)態(tài)路由示例
package main
import (
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/frame/g"
)
func main() {
s := g.Server()
// 一個(gè)簡(jiǎn)單的分頁(yè)路由示例
s.BindHandler("/user/list/{page}.html", func(r *ghttp.Request){
r.Response.Writeln(r.Get("page"))
})
// {xxx} 規(guī)則與 :xxx 規(guī)則混合使用
s.BindHandler("/{object}/:attr/{act}.php", func(r *ghttp.Request){
r.Response.Writeln(r.Get("object"))
r.Response.Writeln(r.Get("attr"))
r.Response.Writeln(r.Get("act"))
})
// 多種模糊匹配規(guī)則混合使用
s.BindHandler("/{class}-{course}/:name/*act", func(r *ghttp.Request){
r.Response.Writeln(r.Get("class"))
r.Response.Writeln(r.Get("course"))
r.Response.Writeln(r.Get("name"))
r.Response.Writeln(r.Get("act"))
})
s.SetPort(8199)
s.Run()
}執(zhí)行后,我們可以通過(guò)?curl?命令或者瀏覽器訪問(wèn)的方式進(jìn)行測(cè)試,以下為測(cè)試結(jié)果:
$ curl -XGET http://127.0.0.1:8199/user/list/1.html
1
$ curl -XGET http://127.0.0.1:8199/user/info/save.php
user
info
save
$ curl -XGET http://127.0.0.1:8199/class3-math/john/score
class3
math
john
score
優(yōu)先級(jí)控制
優(yōu)先級(jí)控制按照深度優(yōu)先策略,主要的幾點(diǎn)因素:
- 層級(jí)越深的規(guī)則優(yōu)先級(jí)越高;
- 同一層級(jí)下,精準(zhǔn)匹配優(yōu)先級(jí)高于模糊匹配;
- 同一層級(jí)下,模糊匹配優(yōu)先級(jí):字段匹配 > 命名匹配 > 模糊匹配;
我們來(lái)看示例(左邊的規(guī)則優(yōu)先級(jí)比右邊高):
/:name > /*any
/user/name > /user/:action
/:name/info > /:name/:action
/:name/:action > /:name/*action
/:name/{action} > /:name/:action
/src/path/del > /src/path
/src/path/del > /src/path/:action
/src/path/*any > /src/path 標(biāo)題名稱:創(chuàng)新互聯(lián)GoFrame教程:GoFrame路由管理-路由規(guī)則
網(wǎng)頁(yè)網(wǎng)址:http://m.5511xx.com/article/ccdogie.html


咨詢
建站咨詢
