新聞中心
對象注冊注冊一個實例化的對象,以后每一個請求都交給該對象(同一對象)處理,該對象常駐內(nèi)存不釋放。

成都創(chuàng)新互聯(lián)長期為上千家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為常山企業(yè)提供專業(yè)的成都做網(wǎng)站、成都網(wǎng)站設(shè)計,常山網(wǎng)站改版等技術(shù)服務(wù)。擁有10多年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
相關(guān)方法:
func (s *Server) BindObject(pattern string, object interface{}, methods ...string) error
func (s *Server) BindObjectMethod(pattern string, object interface{}, method string) error
func (s *Server) BindObjectRest(pattern string, object interface{}) error
對象注冊
我們可以通過?BindObject?方法完成對象的注冊。
package main
import (
"github.com/GOgf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
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 main() {
s := g.Server()
c := new(Controller)
s.BindObject("/object", c)
s.SetPort(8199)
s.Run()
}可以看到,對象在進行路由注冊時便生成了一個對象(對象在?Server?啟動時便生成),此后不管多少請求進入,?Server?都是將請求轉(zhuǎn)交給該對象對應(yīng)的方法進行處理。需要注意的是,公開方法的定義,必須為以下形式:
func(r *ghttp.Request)否則無法完成注冊,調(diào)用注冊方法時會有錯誤提示,例如:
panic: interface conversion: interface {} is xxx, not func(*ghttp.Request)該示例執(zhí)行后,終端輸出的路由表如下:
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
|---------|---------|---------|--------|---------------|--------------------------|------------|
default | default | :8199 | ALL | /object | main.(*Controller).Index |
|---------|---------|---------|--------|---------------|--------------------------|------------|
default | default | :8199 | ALL | /object/index | main.(*Controller).Index |
|---------|---------|---------|--------|---------------|--------------------------|------------|
default | default | :8199 | ALL | /object/show | main.(*Controller).Show |
|---------|---------|---------|--------|---------------|--------------------------|------------|隨后可以通過 http://127.0.0.1:8199/object/show 查看效果。
控制器中的?Index?方法是一個特殊的方法,例如,當(dāng)注冊的路由規(guī)則為?/user?時,?HTTP?請求到?/user?時,將會自動映射到控制器的?Index?方法。也就是說,訪問地址?/user?和?/user/index?將會達(dá)到相同的執(zhí)行效果。
路由內(nèi)置變量
當(dāng)使用?BindObject?方法進行對象注冊時,在路由規(guī)則中可以使用兩個內(nèi)置的變量:?{.struct}?和?{.method}?,前者表示當(dāng)前對象名稱,后者表示當(dāng)前注冊的方法名。我們來看一個例子:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
type Order struct{}
func (o *Order) List(r *ghttp.Request) {
r.Response.Write("list")
}
func main() {
s := g.Server()
o := new(Order)
s.BindObject("/{.struct}-{.method}", o)
s.SetPort(8199)
s.Run()
}package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
type Order struct{}
func (o *Order) List(r *ghttp.Request) {
r.Response.Write("list")
}
func main() {
s := g.Server()
o := new(Order)
s.BindObject("/{.struct}-{.method}", o)
s.SetPort(8199)
s.Run()
}執(zhí)行后,終端輸出的路由表如下:
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
|---------|---------|---------|--------|-------------|--------------------|------------|
default | default | :8199 | ALL | /order-list | main.(*Order).List |
|---------|---------|---------|--------|-------------|--------------------|------------|我們嘗試著訪問 http://127.0.0.1:8199/order-list ,可以看到頁面輸出?list?。如果路由規(guī)則中不使用內(nèi)置變量,那么默認(rèn)的情況下,方法將會被追加到指定的路由規(guī)則末尾。
命名風(fēng)格規(guī)則
通過對象進行路由注冊時,可以根據(jù)對象及方法名稱自動生成路由規(guī)則,默認(rèn)的路由規(guī)則為:當(dāng)方法名稱帶有多個單詞(按照字符大寫區(qū)分單詞)時,路由控制器默認(rèn)會自動使用英文連接符號-進行拼接,因此訪問的時候方法名稱需要帶-號。
例如,方法名為?UserName?時,生成的路由為?user-name?;方法名為?ShowListItems?時,生成的路由為?show-list-items?;以此類推。
此外,我們可以通過?.Server.SetNameToUriType?方法來設(shè)置對象方法名稱的路由生成方式。支持的方式目前有4種,對應(yīng)4個常量定義:
UriTypeDefault = 0 // (默認(rèn))全部轉(zhuǎn)為小寫,單詞以'-'連接符號連接
UriTypeFullName = 1 // 不處理名稱,以原有名稱構(gòu)建成URI
UriTypeAllLower = 2 // 僅轉(zhuǎn)為小寫,單詞間不使用連接符號
UriTypeCamel = 3 // 采用駝峰命名方式注意:需要在通過對象進行路由注冊前進行該參數(shù)的設(shè)置,在路由注冊后設(shè)置將不會生效,那么將使用默認(rèn)規(guī)則。
我們來看一個示例:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
type User struct{}
func (u *User) ShowList(r *ghttp.Request) {
r.Response.Write("list")
}
func main() {
u := new(User)
s1 := g.Server("UriTypeDefault")
s2 := g.Server("UriTypeFullName")
s3 := g.Server("UriTypeAllLower")
s4 := g.Server("UriTypeCamel")
s1.SetNameToUriType(ghttp.UriTypeDefault)
s2.SetNameToUriType(ghttp.UriTypeFullName)
s3.SetNameToUriType(ghttp.UriTypeAllLower)
s4.SetNameToUriType(ghttp.UriTypeCamel)
s1.BindObject("/{.struct}/{.method}", u)
s2.BindObject("/{.struct}/{.method}", u)
s3.BindObject("/{.struct}/{.method}", u)
s4.BindObject("/{.struct}/{.method}", u)
s1.SetPort(8100)
s2.SetPort(8200)
s3.SetPort(8300)
s4.SetPort(8400)
s1.Start()
s2.Start()
s3.Start()
s4.Start()
g.Wait()
}為了對比演示效果,這個示例采用了多?Server?運行方式,將不同的名稱轉(zhuǎn)換方式使用了不同的?Server?來配置運行,因此我們可以方便地在同一個程序中,訪問不同的?Server?(通過不同的端口綁定)看到不同的結(jié)果。
執(zhí)行后,終端輸出的路由表如下:
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
-----------------|---------|---------|--------|-----------------|-----------------------|-------------
UriTypeDefault | default | :8100 | ALL | /user/show-list | main.(*User).ShowList |
-----------------|---------|---------|--------|-----------------|-----------------------|-------------
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
------------------|---------|---------|--------|----------------|-----------------------|-------------
UriTypeFullName | default | :8200 | ALL | /User/ShowList | main.(*User).ShowList |
------------------|---------|---------|--------|----------------|-----------------------|-------------
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
------------------|---------|---------|--------|----------------|-----------------------|-------------
UriTypeAllLower | default | :8300 | ALL | /user/showlist | main.(*User).ShowList |
------------------|---------|---------|--------|----------------|-----------------------|-------------
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
---------------|---------|---------|--------|----------------|-----------------------|-------------
UriTypeCamel | default | :8400 | ALL | /user/showList | main.(*User).ShowList |
---------------|---------|---------|--------|----------------|-----------------------|------------- 可以分別訪問以下URL地址得到期望的結(jié)果:
http://127.0.0.1:8100/user/show-list
http://127.0.0.1:8200/User/ShowList
http://127.0.0.1:8300/user/showlist
http://127.0.0.1:8400/user/showList
對象方法注冊
假如控制器中有若干公開方法,但是我只想注冊其中幾個,其余的方法我不想對外公開,怎么辦?我們可以通過?BindObject?傳遞第三個非必需參數(shù)替換實現(xiàn),參數(shù)支持傳入多個方法名稱,多個名稱以英文,號分隔(方法名稱參數(shù)區(qū)分大小寫)。
示例:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
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 main() {
s := g.Server()
c := new(Controller)
s.BindObject("/object", c, "Show")
s.SetPort(8199)
s.Run()
}執(zhí)行后,終端輸出路由表為:
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
|---------|---------|---------|--------|--------------|-------------------------|------------|
default | default | :8199 | ALL | /object/show | main.(*Controller).Show |
|---------|---------|---------|--------|--------------|-------------------------|------------|
綁定路由方法
我們可以通過?BindObjectMethod?方法綁定指定的路由到指定的方法執(zhí)行(方法名稱參數(shù)區(qū)分大小寫)。
?BindObjectMethod?和?BindObject?的區(qū)別:?BindObjectMethod?將對象中的指定方法與指定路由規(guī)則進行綁定,第三個?method?參數(shù)只能指定一個方法名稱;?BindObject?注冊時,所有的路由都是對象方法名稱按照規(guī)則生成的,第三個?methods?參數(shù)可以指定多個注冊的方法名稱。
來看一個例子:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
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 main() {
s := g.Server()
c := new(Controller)
s.BindObjectMethod("/show", c, "Show")
s.SetPort(8199)
s.Run()
}執(zhí)行后,終端輸出的路由表如下:
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
|---------|---------|---------|--------|-------|-------------------------|------------|
default | default | :8199 | ALL | /show | main.(*Controller).Show |
|---------|---------|---------|--------|-------|-------------------------|------------|
RESTful對象注冊
?RESTful?設(shè)計方式的控制器,通常用于?API?服務(wù)。在這種模式下,?HTTP?的?Method?將會映射到控制器對應(yīng)的方法名稱,例如:?POST?方式將會映射到控制器的?Post?方法中(公開方法,首字母大寫),?DELETE?方式將會映射到控制器的?Delete?方法中,以此類推。其他非?HTTP ?Method??命名的方法,即使是定義的包公開方法,將不會自動注冊,對于應(yīng)用端不可見。當(dāng)然,如果控制器并未定義對應(yīng)?HTTP Method?的方法,該?Method?請求下將會返回 ?HTTP Status 404?。
?GoFrame?的這種?RESTful?對象注冊方式是一種嚴(yán)格的?REST?路由注冊方式,我們可以將控制器的對象看做?REST?中的資源,而其中的?HTTP Method?方法即為?REST?規(guī)范的資源操作方法。如果大家不太熟悉?REST?規(guī)范,或者不想太過嚴(yán)格的?RESTful?路由設(shè)計,那么請忽略該章節(jié)。
我們可以通過?BindObjectRest?方法完成?REST?對象的注冊,示例:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
type Controller struct{}
// RESTFul - GET
func (c *Controller) Get(r *ghttp.Request) {
r.Response.Write("GET")
}
// RESTFul - POST
func (c *Controller) Post(r *ghttp.Request) {
r.Response.Write("POST")
}
// RESTFul - DELETE
func (c *Controller) Delete(r *ghttp.Request) {
r.Response.Write("DELETE")
}
// 該方法無法映射,將會無法訪問到
func (c *Controller) Hello(r *ghttp.Request) {
r.Response.Write("Hello")
}
func main() {
s := g.Server()
c := new(Controller)
s.BindObjectRest("/object", c)
s.SetPort(8199)
s.Run()
}執(zhí)行后,終端輸出路由表如下;
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
|---------|---------|---------|--------|---------|---------------------------|------------|
default | default | :8199 | DELETE | /object | main.(*Controller).Delete |
|---------|---------|---------|--------|---------|---------------------------|------------|
default | default | :8199 | GET | /object | main.(*Controller).Get |
|---------|---------|---------|--------|---------|---------------------------|------------|
default | default | :8199 | POST | /object | main.(*Controller).Post |
|---------|---------|---------|--------|---------|---------------------------|------------|
構(gòu)造方法Init與析構(gòu)方法Shut
對象中的?Init?和?Shut?是兩個在?HTTP?請求流程中被?Server?自動調(diào)用的特殊方法(類似構(gòu)造函數(shù)和析構(gòu)函數(shù)的作用)。
Init回調(diào)方法
對象收到請求時的初始化方法,在服務(wù)接口調(diào)用之前被回調(diào)執(zhí)行。
方法定義:
// "構(gòu)造函數(shù)"對象方法
func (c *Controller) Init(r *ghttp.Request) {
}
Shut回調(diào)方法
當(dāng)請求結(jié)束時被?Server?自動調(diào)用,可以用于對象執(zhí)行一些收尾處理的操作。
方法定義:
// "析構(gòu)函數(shù)"對象方法
func (c *Controller) Shut(r *ghttp.Request) {
}舉個例子:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
type Controller struct{}
func (c *Controller) Init(r *ghttp.Request) {
r.Response.Writeln("Init")
}
func (c *Controller) Shut(r *ghttp.Request) {
r.Response.Writeln("Shut")
}
func (c *Controller) Hello(r *ghttp.Request) {
r.Response.Writeln("Hello")
}
func main() {
s := g.Server()
c := new(Controller)
s.BindObject("/object", c)
s.SetPort(8199)
s.Run()
}執(zhí)行后,終端輸出路由表如下:
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
|---------|---------|---------|--------|---------------|--------------------------|------------|
default | default | :8199 | ALL | /object/hello | main.(*Controller).Hello |
|---------|---------|---------|--------|---------------|--------------------------|------------|可以看到,并沒有自動注冊?Init?和?Shut?這兩個方法的路由,我們訪問 http://127.0.0.1:8199/object/hello 后,輸出結(jié)果為:
Init
Hello
Shut 當(dāng)前名稱:創(chuàng)新互聯(lián)GoFrame教程:GoFrame路由注冊-對象注冊
分享URL:http://www.dlmjj.cn/article/ccddjig.html


咨詢
建站咨詢
