diff --git a/g/net/ghttp/ghttp_server_service_controller.go b/g/net/ghttp/ghttp_server_service_controller.go index 336da858f..4f50c2c0d 100644 --- a/g/net/ghttp/ghttp_server_service_controller.go +++ b/g/net/ghttp/ghttp_server_service_controller.go @@ -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) } diff --git a/g/net/ghttp/ghttp_server_service_handler.go b/g/net/ghttp/ghttp_server_service_handler.go index 22cec78df..aae61079d 100644 --- a/g/net/ghttp/ghttp_server_service_handler.go +++ b/g/net/ghttp/ghttp_server_service_handler.go @@ -47,13 +47,17 @@ func (s *Server) bindHandlerByMap(m handlerMap) error { // 规则1:pattern中的URI包含{.struct}关键字,则替换该关键字为结构体名称; // 规则1:pattern中的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) diff --git a/g/net/ghttp/ghttp_server_service_object.go b/g/net/ghttp/ghttp_server_service_object.go index 52ebea54f..bfc18221d 100644 --- a/g/net/ghttp/ghttp_server_service_object.go +++ b/g/net/ghttp/ghttp_server_service_object.go @@ -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) } diff --git a/geg/frame/mvc/controller/demo/method.go b/geg/frame/mvc/controller/demo/method.go index ed734fc09..224df5c50 100644 --- a/geg/frame/mvc/controller/demo/method.go +++ b/geg/frame/mvc/controller/demo/method.go @@ -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() { diff --git a/geg/frame/mvc/controller/demo/object_method.go b/geg/frame/mvc/controller/demo/object_method.go index 3922787b3..9063293dc 100644 --- a/geg/frame/mvc/controller/demo/object_method.go +++ b/geg/frame/mvc/controller/demo/object_method.go @@ -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) { diff --git a/geg/other/test.go b/geg/other/test.go index 51c69f579..c201d4e0f 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -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"]) } \ No newline at end of file