日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
創(chuàng)新互聯(lián)GoFrame教程:GoFrame路由管理-路由規(guī)則

?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)因素:

  1. 層級(jí)越深的規(guī)則優(yōu)先級(jí)越高;
  2. 同一層級(jí)下,精準(zhǔn)匹配優(yōu)先級(jí)高于模糊匹配;
  3. 同一層級(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