您好,登錄后才能下訂單哦!
這篇文章主要介紹了Beego AutoRouter工作原理是什么的相關(guān)知識,內(nèi)容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Beego AutoRouter工作原理是什么文章都會有所收獲,下面我們一起來看看吧。
Beego的路由設(shè)計靈感是sinatra,剛開始并不支持自動路由,項目的每一個路由都需要開發(fā)者配置。
不過,在Beego里面注冊一個路由是十分簡單的,不信你看:
import "github.com/beego/beego/v2/server/web" type ReganYueController struct { web.Controller }
接下來我們可以添加一個方法,也可以重寫Get,Post,Delete等方法來響應客戶端不同的請求方式。
import "github.com/beego/beego/v2/server/web" type ReganYueController struct { web.Controller } func (u *ReganYueController) HelloWorld() { u.Ctx.WriteString("Welcome, Regan Yue") } func main() { web.AutoRouter(&ReganYueController{}) web.Run() }
該處web.AutoRouter(&ReganYueController{})
就是使用的自動路由,如果是以前的話,我們還需要配置路由???? 。例如以下這種形式:
beego.Router("/", &IndexController{})
對于下面這段代碼,有幾點需要注意:
func (u *ReganYueController) HelloWorld() { u.Ctx.WriteString("Welcome, Regan Yue") }
這個處理HTTP請求的方法必須是公共方法(首字母要大寫),并且不能有參數(shù),不能有返回值,若非如此,可能會發(fā)生Panic。
影響因素有三:
RouterCaseSensitive
的值。
Controller
的名字
方法名字
比如我們上面ReganYueController的名字是ReganYue,而方法名字是HelloWorld,那么就會有以下幾種情況出現(xiàn):
如果RouterCaseSensitive
為true
,那么AutoRouter就會注冊兩個路由,其中一個是/ReganYue/HelloWorld/*
,另一個是/reganyue/helloworld/*
。
如果RouterCaseSensitive
為false
,那么AutoRouter只會注冊一個路由,即/reganyue/helloworld/*
。
先看看web.AutoRouter()
// AutoRouter see HttpServer.AutoRouter func AutoRouter(c ControllerInterface) *HttpServer { return BeeApp.AutoRouter(c) }
web.AutoRouter()
馬上又指向(app *HttpServer) AutoRouter(c ControllerInterface)
// AutoRouter adds defined controller handler to BeeApp. // it's same to HttpServer.AutoRouter. // if beego.AddAuto(&MainContorlller{}) and MainController has methods List and Page, // visit the url /main/list to exec List function or /main/page to exec Page function. func (app *HttpServer) AutoRouter(c ControllerInterface) *HttpServer { app.Handlers.AddAuto(c) return app }
前面?zhèn)鱽淼闹髡ZBeeApp
執(zhí)行該處程序:
BeeApp是一個應用實例,使用NewHttpSever()創(chuàng)建,繼續(xù)跟進,發(fā)現(xiàn)是根據(jù)Bconfig
這個配置文件創(chuàng)建的,
// NewHttpServerWithCfg will create an sever with specific cfg func NewHttpServerWithCfg(cfg *Config) *HttpServer { cr := NewControllerRegisterWithCfg(cfg) app := &HttpServer{ Handlers: cr, Server: &http.Server{}, Cfg: cfg, } return app }
上圖即配置Bconfig的主要結(jié)構(gòu)。
到此我們對于BeeApp已經(jīng)有一定了解了,下面我們回過頭來看看app.Handlers.AddAuto(c)
。
先看看這個c
是什么,它的類型是ControllerInterface
,我們現(xiàn)在進去看看。
這個c是用來統(tǒng)一所有controller handler的接口。
根據(jù)上圖我們可以知道,這個app.Handles就是ControllerRegister,再來看看ControllerRegister的AddAuto方法:
func (p *ControllerRegister) AddAuto(c ControllerInterface) { p.AddAutoPrefix("/", c) }
AddAuto又指向AddAutoPrefix,這個AddAutoPrefix有什么用,我們先給出一個例子,然后再來看源碼。
beego.AddAutoPrefix("/admin",&MainContorlller{})
如果MainContorlller
有兩個方法List
、Page
。那么我們可以訪問/admin/main/list
來執(zhí)行List
函數(shù),訪問/admin/main/page
來執(zhí)行Page
函數(shù)
來看看ControllerRegister的AddAutoPrefix方法:
func (p *ControllerRegister) AddAutoPrefix(prefix string, c ControllerInterface) { //對傳入的Controller做反射 reflectVal := reflect.ValueOf(c) //獲取傳入的Controller的類型 rt := reflectVal.Type() //因為c是指針,所以要用Indirect方法獲取指針指向的變量類型 ct := reflect.Indirect(reflectVal).Type() //使用Beego注冊controller的名稱后面有Controller,這里把它去掉得到controllerName。 controllerName := strings.TrimSuffix(ct.Name(), "Controller") // for i := 0; i < rt.NumMethod(); i++ { if !utils.InSlice(rt.Method(i).Name, exceptMethod) { route := &ControllerInfo{} route.routerType = routerTypeBeego route.methods = map[string]string{"*": rt.Method(i).Name} route.controllerType = ct pattern := path.Join(prefix, strings.ToLower(controllerName), strings.ToLower(rt.Method(i).Name), "*") patternInit := path.Join(prefix, controllerName, rt.Method(i).Name, "*") patternFix := path.Join(prefix, strings.ToLower(controllerName), strings.ToLower(rt.Method(i).Name)) patternFixInit := path.Join(prefix, controllerName, rt.Method(i).Name) route.pattern = pattern for m := range HTTPMETHOD { p.addToRouter(m, pattern, route) p.addToRouter(m, patternInit, route) p.addToRouter(m, patternFix, route) p.addToRouter(m, patternFixInit, route) } } } }
reflectVal.Type()
直接的獲取傳入的Controller的類型,而reflect.Indirect(reflectVal).Type()
,interface其實就是兩個指針,一個指向類型信息,一個指向?qū)嶋H的對象,用Indirect方法獲取指針指向的實際變量的類型。
在runtime/runtime2.go
可以了解interface其實就是兩個指針:
type iface struct { tab *itab //類型信息 data unsafe.Pointer //實際對象指針 } type itab struct { inter *interfacetype //接口類型 _type *_type //實際對象類型 hash uint32 _ [4]byte fun [1]uintptr //實際對象方法地址 }
接下來是for i := 0; i < rt.NumMethod(); i++
,我們來看看這個NumMethod()
,可以看到這個方法獲得interface類型的方法數(shù)量。
utils.InSlice()方法正如其名:
func InSlice(v string, sl []string) bool { for _, vv := range sl { if vv == v { return true } } return false }
該方法是用來判斷字符串v是不是在字符串切片sl里面。
此處判斷方法名是不是在exceptMethod里面。
下面是exceptMethod的內(nèi)容:
exceptMethod = []string{"Init", "Prepare", "Finish", "Render", "RenderString", "RenderBytes", "Redirect", "Abort", "StopRun", "UrlFor", "ServeJSON", "ServeJSONP", "ServeYAML", "ServeXML", "Input", "ParseForm", "GetString", "GetStrings", "GetInt", "GetBool", "GetFloat", "GetFile", "SaveToFile", "StartSession", "SetSession", "GetSession", "DelSession", "SessionRegenerateID", "DestroySession", "IsAjax", "GetSecureCookie", "SetSecureCookie", "XsrfToken", "CheckXsrfCookie", "XsrfFormHtml", "GetControllerAndAction", "ServeFormatted"}
接下來創(chuàng)建了一個結(jié)構(gòu)體,記錄了controller的信息,下面幾行代碼就生成了每個方法對應的controller信息。
controller的pattern這里生成了4個模式:
prefix/全小寫的controllerName/全小寫的方法名/*
prefix/controllerName/方法名/*
prefix/全小寫的controllerName/全小寫的方法名
prefix/controllerName/方法名
然后對每一種HTTP方法:
都使用addToRouter
方法用四種模式執(zhí)行一遍。
下面看看addToRouter。
func (p *ControllerRegister) addToRouter(method, pattern string, r *ControllerInfo) { if !p.cfg.RouterCaseSensitive { pattern = strings.ToLower(pattern) } if t, ok := p.routers[method]; ok { t.AddRouter(pattern, r) } else { t := NewTree() t.AddRouter(pattern, r) p.routers[method] = t } }
如果RouterCaseSensitive
為true
,那么AutoRouter就會注冊兩個路由,其中一個是/ReganYue/HelloWorld/*
,另一個是/reganyue/helloworld/*
。
如果RouterCaseSensitive
為false
,那么AutoRouter只會注冊一個路由,即/reganyue/helloworld/*
。
然后將method傳給ControllerRegister,看是不是注冊成功。
成功就執(zhí)行:t.AddRouter(pattern, r)
添加路由。
否則就執(zhí)行:
t := NewTree() t.AddRouter(pattern, r) p.routers[method] = t
關(guān)于“Beego AutoRouter工作原理是什么”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“Beego AutoRouter工作原理是什么”知識都有一定的了解,大家如果還想學習更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。