调整BindControllerMethod及BindObjectMethod逻辑为绑定路由到指定的方法执行

This commit is contained in:
John 2018-08-16 21:33:47 +08:00
parent 2337b86815
commit 21a758b3a2
6 changed files with 82 additions and 63 deletions

View File

@ -15,9 +15,14 @@ import (
// 绑定控制器控制器需要实现gmvc.Controller接口
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
// 第三个参数methods用以指定需要注册的方法支持多个方法名称多个方法以英文“,”号分隔,区分大小写
func (s *Server)BindController(pattern string, c Controller, methods...string) error {
methodMap := (map[string]bool)(nil)
if len(methods) > 0 {
return s.BindControllerMethod(pattern, c, strings.Join(methods, ","))
methodMap = make(map[string]bool)
for _, v := range strings.Split(methods[0], ",") {
methodMap[strings.TrimSpace(v)] = true
}
}
// 遍历控制器获取方法列表并构造成uri
m := make(handlerMap)
@ -26,10 +31,13 @@ func (s *Server)BindController(pattern string, c Controller, methods...string) e
sname := t.Elem().Name()
for i := 0; i < v.NumMethod(); i++ {
mname := t.Method(i).Name
if methodMap != nil && !methodMap[mname] {
continue
}
if mname == "Init" || mname == "Shut" || mname == "Exit" {
continue
}
key := s.mergeBuildInNameToPattern(pattern, sname, mname)
key := s.mergeBuildInNameToPattern(pattern, sname, mname, true)
m[key] = &handlerItem {
ctype : v.Elem().Type(),
fname : mname,
@ -54,41 +62,39 @@ func (s *Server)BindController(pattern string, c Controller, methods...string) e
return s.bindHandlerByMap(m)
}
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
// 第三个参数methods支持多个方法注册多个方法以英文“,”号分隔,不区分大小写
func (s *Server)BindControllerMethod(pattern string, c Controller, methods string) error {
// 绑定路由到指定的方法执行
func (s *Server)BindControllerMethod(pattern string, c Controller, method string) error {
m := make(handlerMap)
v := reflect.ValueOf(c)
e := v.Type().Elem()
t := v.Elem().Type()
sname := e.Name()
for _, method := range strings.Split(methods, ",") {
mname := strings.TrimSpace(method)
if !v.MethodByName(mname).IsValid() {
return errors.New("invalid method name:" + mname)
mname := strings.TrimSpace(method)
if !v.MethodByName(mname).IsValid() {
return errors.New("invalid method name:" + mname)
}
key := s.mergeBuildInNameToPattern(pattern, sname, mname, false)
m[key] = &handlerItem {
ctype : t,
fname : mname,
faddr : nil,
}
// 如果方法中带有Index方法那么额外自动增加一个路由规则匹配主URI
if strings.EqualFold(mname, "Index") {
p := key
if strings.EqualFold(p[len(p) - 6:], "/index") {
p = p[0 : len(p) - 6]
if len(p) == 0 {
p = "/"
}
}
key := s.mergeBuildInNameToPattern(pattern, sname, mname)
m[key] = &handlerItem {
m[p] = &handlerItem {
ctype : t,
fname : mname,
faddr : nil,
}
// 如果方法中带有Index方法那么额外自动增加一个路由规则匹配主URI
if strings.EqualFold(mname, "Index") {
p := key
if strings.EqualFold(p[len(p) - 6:], "/index") {
p = p[0 : len(p) - 6]
if len(p) == 0 {
p = "/"
}
}
m[p] = &handlerItem {
ctype : t,
fname : mname,
faddr : nil,
}
}
}
return s.bindHandlerByMap(m)
}

View File

@ -47,13 +47,17 @@ func (s *Server) bindHandlerByMap(m handlerMap) error {
// 规则1pattern中的URI包含{.struct}关键字,则替换该关键字为结构体名称;
// 规则1pattern中的URI包含{.method}关键字,则替换该关键字为方法名称;
// 规则2如果不满足规则1那么直接将防发明附加到pattern中的URI后面
func (s *Server) mergeBuildInNameToPattern(pattern string, structName, methodName string) string {
func (s *Server) mergeBuildInNameToPattern(pattern string, structName, methodName string, allowAppend bool) string {
structName = s.nameToUrlPart(structName)
methodName = s.nameToUrlPart(methodName)
pattern = strings.Replace(pattern, "{.struct}", structName, -1)
if strings.Index(pattern, "{.method}") != -1 {
return strings.Replace(pattern, "{.method}", methodName, -1)
}
// 不允许将方法名称append到路由末尾
if !allowAppend {
return pattern
}
// 检测域名后缀
array := strings.Split(pattern, "@")
// 分离URI(其实可能包含HTTP Method)

View File

@ -14,25 +14,32 @@ import (
)
// 绑定对象到URI请求处理中会自动识别方法名称并附加到对应的URI地址后面
// 需要注意对象方法的定义必须按照ghttp.HandlerFunc来定义
// 第三个参数methods用以指定需要注册的方法支持多个方法名称多个方法以英文“,”号分隔,区分大小写
func (s *Server)BindObject(pattern string, obj interface{}, methods...string) error {
methodMap := (map[string]bool)(nil)
if len(methods) > 0 {
return s.BindObjectMethod(pattern, obj, strings.Join(methods, ","))
methodMap = make(map[string]bool)
for _, v := range strings.Split(methods[0], ",") {
methodMap[strings.TrimSpace(v)] = true
}
}
m := make(handlerMap)
v := reflect.ValueOf(obj)
t := v.Type()
sname := t.Elem().Name()
for i := 0; i < v.NumMethod(); i++ {
method := t.Method(i).Name
key := s.mergeBuildInNameToPattern(pattern, sname, method)
mname := t.Method(i).Name
if methodMap != nil && !methodMap[mname] {
continue
}
key := s.mergeBuildInNameToPattern(pattern, sname, mname, true)
m[key] = &handlerItem {
ctype : nil,
fname : "",
faddr : v.Method(i).Interface().(func(*Request)),
}
// 如果方法中带有Index方法那么额外自动增加一个路由规则匹配主URI
if strings.EqualFold(method, "Index") {
if strings.EqualFold(mname, "Index") {
p := key
if strings.EqualFold(p[len(p) - 6:], "/index") {
p = p[0 : len(p) - 6]
@ -52,39 +59,38 @@ func (s *Server)BindObject(pattern string, obj interface{}, methods...string) er
// 绑定对象到URI请求处理中会自动识别方法名称并附加到对应的URI地址后面
// 第三个参数methods支持多个方法注册多个方法以英文“,”号分隔,区分大小写
func (s *Server)BindObjectMethod(pattern string, obj interface{}, methods string) error {
func (s *Server)BindObjectMethod(pattern string, obj interface{}, method string) error {
m := make(handlerMap)
v := reflect.ValueOf(obj)
t := v.Type()
sname := t.Elem().Name()
for _, method := range strings.Split(methods, ",") {
mname := strings.TrimSpace(method)
fval := v.MethodByName(mname)
if !fval.IsValid() {
return errors.New("invalid method name:" + mname)
mname := strings.TrimSpace(method)
fval := v.MethodByName(mname)
if !fval.IsValid() {
return errors.New("invalid method name:" + mname)
}
key := s.mergeBuildInNameToPattern(pattern, sname, mname, false)
m[key] = &handlerItem{
ctype : nil,
fname : "",
faddr : fval.Interface().(func(*Request)),
}
// 如果方法中带有Index方法那么额外自动增加一个路由规则匹配主URI
if strings.EqualFold(mname, "Index") {
p := key
if strings.EqualFold(p[len(p) - 6:], "/index") {
p = p[0 : len(p) - 6]
if len(p) == 0 {
p = "/"
}
}
key := s.mergeBuildInNameToPattern(pattern, sname, mname)
m[key] = &handlerItem{
m[p] = &handlerItem {
ctype : nil,
fname : "",
faddr : fval.Interface().(func(*Request)),
}
// 如果方法中带有Index方法那么额外自动增加一个路由规则匹配主URI
if strings.EqualFold(mname, "Index") {
p := key
if strings.EqualFold(p[len(p) - 6:], "/index") {
p = p[0 : len(p) - 6]
if len(p) == 0 {
p = "/"
}
}
m[p] = &handlerItem {
ctype : nil,
fname : "",
faddr : fval.Interface().(func(*Request)),
}
}
}
return s.bindHandlerByMap(m)
}

View File

@ -10,7 +10,11 @@ type Method struct {
}
func init() {
g.Server().BindControllerMethod("/method", &Method{}, "Name, Age")
// 第三个参数指定主要注册的方法,其他方法不注册,方法名称会自动追加到给定路由后面,构成新路由
// 以下注册会中注册两个新路由: /method/name, /method/age
g.Server().BindController("/method", new(Method), "Name, Age")
// 绑定路由到指定的方法执行,以下注册只会注册一个路由: /method-name
g.Server().BindControllerMethod("/method-name", new(Method), "Name")
}
func (c *Method) Name() {

View File

@ -9,8 +9,9 @@ type ObjectMethod struct {}
func init() {
obj := &ObjectMethod{}
g.Server().BindObjectMethod("/object-method", obj, "Show1, Show2, Show3")
g.Server().Domain("localhost").BindObjectMethod("/object-method", obj, "Show4")
g.Server().BindObject("/object-method", obj, "Show1, Show2, Show3")
g.Server().BindObjectMethod("/object-method-show1", obj, "Show1")
g.Server().Domain("localhost").BindObject("/object-method", obj, "Show4")
}
func (o *ObjectMethod) Show1(r *ghttp.Request) {

View File

@ -2,12 +2,10 @@ package main
import (
"fmt"
"path/filepath"
"os"
)
func main() {
fmt.Println(filepath.Abs(filepath.Dir(os.Args[0])))
methodMap := make(map[string]bool)
methodMap["t"] = true
fmt.Println(methodMap["t"])
}