mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 11:18:02 +08:00
ghttp.Request增加对GET/POST/Router参数的设置功能
This commit is contained in:
parent
6acd228fde
commit
c1d84c2a67
@ -20,13 +20,19 @@ func (r *Request) initPost() {
|
||||
}
|
||||
}
|
||||
|
||||
// 设置GET参数,仅在ghttp.Server内有效,**注意并发安全性**
|
||||
// 设置POST参数,仅在ghttp.Server内有效,**注意并发安全性**
|
||||
func (r *Request) SetPost(k string, v string) {
|
||||
r.initPost()
|
||||
r.PostForm[k] = []string{v}
|
||||
}
|
||||
|
||||
func (r *Request) AddPost(k string, v string) {
|
||||
r.initPost()
|
||||
r.PostForm[k] = append(r.PostForm[k], v)
|
||||
}
|
||||
|
||||
// 获得post参数
|
||||
func (r *Request) GetPost(k string) string {
|
||||
func (r *Request) GetPost(k string) []string {
|
||||
r.initPost()
|
||||
if v, ok := r.PostForm[k]; ok {
|
||||
return v
|
||||
|
@ -13,23 +13,20 @@ import (
|
||||
// 初始化GET请求参数
|
||||
func (r *Request) initGet() {
|
||||
if !r.parsedGet.Val() {
|
||||
if len(r.queryVars) == 0 {
|
||||
r.parsedGet.Set(true)
|
||||
r.queryVars = r.URL.Query()
|
||||
} else {
|
||||
for k, v := range r.URL.Query() {
|
||||
r.queryVars[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设置GET参数,仅在ghttp.Server内有效,**注意并发安全性**
|
||||
func (r *Request) SetQuery(k string, v string) {
|
||||
r.initGet()
|
||||
r.queryVars[k] = []string{v}
|
||||
}
|
||||
|
||||
// 添加GET参数,构成[]string
|
||||
func (r *Request) AddQuery(k string, v string) {
|
||||
r.initGet()
|
||||
r.queryVars[k] = append(r.queryVars[k], v)
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,14 @@
|
||||
|
||||
package ghttp
|
||||
|
||||
func (r *Request) SetRouterString(k, v string) {
|
||||
r.routerVars[k] = []string{v}
|
||||
}
|
||||
|
||||
func (r *Request) AddRouterString(k, v string) {
|
||||
r.routerVars[k] = append(r.routerVars[k], v)
|
||||
}
|
||||
|
||||
// 获得路由解析参数
|
||||
func (r *Request) GetRouterString(k string) string {
|
||||
if v := r.GetRouterArray(k); v != nil {
|
||||
|
@ -1,265 +0,0 @@
|
||||
// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
// 服务注册.
|
||||
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"reflect"
|
||||
"gitee.com/johng/gf/g/util/gstr"
|
||||
)
|
||||
|
||||
// 绑定URI到操作函数/方法
|
||||
// pattern的格式形如:/user/list, put:/user, delete:/user, post:/user@johng.cn
|
||||
// 支持RESTful的请求格式,具体业务逻辑由绑定的处理方法来执行
|
||||
func (s *Server)bindHandlerItem(pattern string, item *handlerItem) error {
|
||||
if s.status == 1 {
|
||||
return errors.New("server handlers cannot be changed while running")
|
||||
}
|
||||
return s.setHandler(pattern, item)
|
||||
}
|
||||
|
||||
// 通过映射数组绑定URI到操作函数/方法
|
||||
func (s *Server)bindHandlerByMap(m handlerMap) error {
|
||||
for p, h := range m {
|
||||
if err := s.bindHandlerItem(p, h); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 将内置的名称按照设定的规则合并到pattern中,内置名称按照{.xxx}规则命名。
|
||||
// 规则1:pattern中的URI包含{.struct}关键字,则替换该关键字为结构体名称;
|
||||
// 规则1:pattern中的URI包含{.method}关键字,则替换该关键字为方法名称;
|
||||
// 规则2:如果不满足规则1,那么直接将防发明附加到pattern中的URI后面;
|
||||
func (s *Server) mergeBuildInNameToPattern(pattern string, structName, methodName string) 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)
|
||||
}
|
||||
// 检测域名后缀
|
||||
array := strings.Split(pattern, "@")
|
||||
// 分离URI(其实可能包含HTTP Method)
|
||||
uri := array[0]
|
||||
uri = strings.TrimRight(uri, "/") + "/" + methodName
|
||||
// 加上指定域名后缀
|
||||
if len(array) > 1 {
|
||||
return uri + "@" + array[1]
|
||||
}
|
||||
return uri
|
||||
}
|
||||
|
||||
// 将给定的名称转换为URL规范格式。
|
||||
// 规范1: 全部转换为小写;
|
||||
// 规范2: 方法名中间存在大写字母,转换为小写URI地址以“-”号链接每个单词;
|
||||
func (s *Server) nameToUrlPart(name string) string {
|
||||
part := ""
|
||||
for i := 0; i < len(name); i++ {
|
||||
if i > 0 && gstr.IsLetterUpper(name[i]) {
|
||||
part += "-"
|
||||
}
|
||||
part += string(name[i])
|
||||
}
|
||||
return strings.ToLower(part)
|
||||
}
|
||||
|
||||
// 注意该方法是直接绑定函数的内存地址,执行的时候直接执行该方法,不会存在初始化新的控制器逻辑
|
||||
func (s *Server)BindHandler(pattern string, handler HandlerFunc) error {
|
||||
return s.bindHandlerItem(pattern, &handlerItem{
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : handler,
|
||||
})
|
||||
}
|
||||
|
||||
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面
|
||||
// 需要注意对象方法的定义必须按照ghttp.HandlerFunc来定义
|
||||
func (s *Server)BindObject(pattern string, obj interface{}) error {
|
||||
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)
|
||||
m[key] = &handlerItem {
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : v.Method(i).Interface().(func(*Request)),
|
||||
}
|
||||
// 如果方法中带有Index方法,那么额外自动增加一个路由规则匹配主URI
|
||||
if strings.EqualFold(method, "Index") {
|
||||
p := key
|
||||
if strings.EqualFold(p[len(p) - 6:], "/index") {
|
||||
p = p[0 : len(p) - 6]
|
||||
}
|
||||
m[p] = &handlerItem {
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : v.Method(i).Interface().(func(*Request)),
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面
|
||||
// 第三个参数methods支持多个方法注册,多个方法以英文“,”号分隔,区分大小写
|
||||
func (s *Server)BindObjectMethod(pattern string, obj interface{}, methods 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)
|
||||
}
|
||||
key := s.mergeBuildInNameToPattern(pattern, sname, mname)
|
||||
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]
|
||||
}
|
||||
m[p] = &handlerItem {
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : fval.Interface().(func(*Request)),
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面
|
||||
// 需要注意对象方法的定义必须按照ghttp.HandlerFunc来定义
|
||||
func (s *Server)BindObjectRest(pattern string, obj interface{}) error {
|
||||
m := make(handlerMap)
|
||||
v := reflect.ValueOf(obj)
|
||||
t := v.Type()
|
||||
for i := 0; i < v.NumMethod(); i++ {
|
||||
name := t.Method(i).Name
|
||||
method := strings.ToUpper(name)
|
||||
if _, ok := s.methodsMap[method]; !ok {
|
||||
continue
|
||||
}
|
||||
key := name + ":" + pattern
|
||||
m[key] = &handlerItem {
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : v.Method(i).Interface().(func(*Request)),
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
// 绑定控制器,控制器需要实现gmvc.Controller接口
|
||||
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
|
||||
func (s *Server)BindController(pattern string, c Controller) error {
|
||||
// 遍历控制器,获取方法列表,并构造成uri
|
||||
m := make(handlerMap)
|
||||
v := reflect.ValueOf(c)
|
||||
t := v.Type()
|
||||
sname := t.Elem().Name()
|
||||
for i := 0; i < v.NumMethod(); i++ {
|
||||
mname := t.Method(i).Name
|
||||
if mname == "Init" || mname == "Shut" || mname == "Exit" {
|
||||
continue
|
||||
}
|
||||
key := s.mergeBuildInNameToPattern(pattern, sname, mname)
|
||||
m[key] = &handlerItem {
|
||||
ctype : v.Elem().Type(),
|
||||
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]
|
||||
}
|
||||
m[p] = &handlerItem {
|
||||
ctype : v.Elem().Type(),
|
||||
fname : mname,
|
||||
faddr : nil,
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
|
||||
// 第三个参数methods支持多个方法注册,多个方法以英文“,”号分隔,不区分大小写
|
||||
func (s *Server)BindControllerMethod(pattern string, c Controller, methods 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)
|
||||
}
|
||||
key := s.mergeBuildInNameToPattern(pattern, sname, mname)
|
||||
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]
|
||||
}
|
||||
m[p] = &handlerItem {
|
||||
ctype : t,
|
||||
fname : mname,
|
||||
faddr : nil,
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
// 绑定控制器(RESTFul),控制器需要实现gmvc.Controller接口
|
||||
// 方法会识别HTTP方法,并做REST绑定处理,例如:Post方法会绑定到HTTP POST的方法请求处理,Delete方法会绑定到HTTP DELETE的方法请求处理
|
||||
// 因此只会绑定HTTP Method对应的方法,其他方法不会自动注册绑定
|
||||
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
|
||||
func (s *Server)BindControllerRest(pattern string, c Controller) error {
|
||||
// 遍历控制器,获取方法列表,并构造成uri
|
||||
m := make(handlerMap)
|
||||
v := reflect.ValueOf(c)
|
||||
t := v.Type()
|
||||
// 如果存在与HttpMethod对应名字的方法,那么绑定这些方法
|
||||
for i := 0; i < v.NumMethod(); i++ {
|
||||
name := t.Method(i).Name
|
||||
method := strings.ToUpper(name)
|
||||
if _, ok := s.methodsMap[method]; !ok {
|
||||
continue
|
||||
}
|
||||
key := name + ":" + pattern
|
||||
m[key] = &handlerItem {
|
||||
ctype : v.Elem().Type(),
|
||||
fname : name,
|
||||
faddr : nil,
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
113
g/net/ghttp/ghttp_server_service_controller.go
Normal file
113
g/net/ghttp/ghttp_server_service_controller.go
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
// 服务注册.
|
||||
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// 绑定控制器,控制器需要实现gmvc.Controller接口
|
||||
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
|
||||
func (s *Server)BindController(pattern string, c Controller, methods...string) error {
|
||||
if len(methods) > 0 {
|
||||
return s.BindControllerMethod(pattern, c, strings.Join(methods, ","))
|
||||
}
|
||||
// 遍历控制器,获取方法列表,并构造成uri
|
||||
m := make(handlerMap)
|
||||
v := reflect.ValueOf(c)
|
||||
t := v.Type()
|
||||
sname := t.Elem().Name()
|
||||
for i := 0; i < v.NumMethod(); i++ {
|
||||
mname := t.Method(i).Name
|
||||
if mname == "Init" || mname == "Shut" || mname == "Exit" {
|
||||
continue
|
||||
}
|
||||
key := s.mergeBuildInNameToPattern(pattern, sname, mname)
|
||||
m[key] = &handlerItem {
|
||||
ctype : v.Elem().Type(),
|
||||
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]
|
||||
}
|
||||
m[p] = &handlerItem {
|
||||
ctype : v.Elem().Type(),
|
||||
fname : mname,
|
||||
faddr : nil,
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
|
||||
// 第三个参数methods支持多个方法注册,多个方法以英文“,”号分隔,不区分大小写
|
||||
func (s *Server)BindControllerMethod(pattern string, c Controller, methods 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)
|
||||
}
|
||||
key := s.mergeBuildInNameToPattern(pattern, sname, mname)
|
||||
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]
|
||||
}
|
||||
m[p] = &handlerItem {
|
||||
ctype : t,
|
||||
fname : mname,
|
||||
faddr : nil,
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
// 绑定控制器(RESTFul),控制器需要实现gmvc.Controller接口
|
||||
// 方法会识别HTTP方法,并做REST绑定处理,例如:Post方法会绑定到HTTP POST的方法请求处理,Delete方法会绑定到HTTP DELETE的方法请求处理
|
||||
// 因此只会绑定HTTP Method对应的方法,其他方法不会自动注册绑定
|
||||
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
|
||||
func (s *Server)BindControllerRest(pattern string, c Controller) error {
|
||||
// 遍历控制器,获取方法列表,并构造成uri
|
||||
m := make(handlerMap)
|
||||
v := reflect.ValueOf(c)
|
||||
t := v.Type()
|
||||
// 如果存在与HttpMethod对应名字的方法,那么绑定这些方法
|
||||
for i := 0; i < v.NumMethod(); i++ {
|
||||
name := t.Method(i).Name
|
||||
method := strings.ToUpper(name)
|
||||
if _, ok := s.methodsMap[method]; !ok {
|
||||
continue
|
||||
}
|
||||
key := name + ":" + pattern
|
||||
m[key] = &handlerItem {
|
||||
ctype : v.Elem().Type(),
|
||||
fname : name,
|
||||
faddr : nil,
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
80
g/net/ghttp/ghttp_server_service_handler.go
Normal file
80
g/net/ghttp/ghttp_server_service_handler.go
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
// 服务注册.
|
||||
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"gitee.com/johng/gf/g/util/gstr"
|
||||
)
|
||||
|
||||
// 注意该方法是直接绑定函数的内存地址,执行的时候直接执行该方法,不会存在初始化新的控制器逻辑
|
||||
func (s *Server)BindHandler(pattern string, handler HandlerFunc) error {
|
||||
return s.bindHandlerItem(pattern, &handlerItem{
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : handler,
|
||||
})
|
||||
}
|
||||
|
||||
// 绑定URI到操作函数/方法
|
||||
// pattern的格式形如:/user/list, put:/user, delete:/user, post:/user@johng.cn
|
||||
// 支持RESTful的请求格式,具体业务逻辑由绑定的处理方法来执行
|
||||
func (s *Server)bindHandlerItem(pattern string, item *handlerItem) error {
|
||||
if s.status == 1 {
|
||||
return errors.New("server handlers cannot be changed while running")
|
||||
}
|
||||
return s.setHandler(pattern, item)
|
||||
}
|
||||
|
||||
// 通过映射数组绑定URI到操作函数/方法
|
||||
func (s *Server)bindHandlerByMap(m handlerMap) error {
|
||||
for p, h := range m {
|
||||
if err := s.bindHandlerItem(p, h); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 将内置的名称按照设定的规则合并到pattern中,内置名称按照{.xxx}规则命名。
|
||||
// 规则1:pattern中的URI包含{.struct}关键字,则替换该关键字为结构体名称;
|
||||
// 规则1:pattern中的URI包含{.method}关键字,则替换该关键字为方法名称;
|
||||
// 规则2:如果不满足规则1,那么直接将防发明附加到pattern中的URI后面;
|
||||
func (s *Server) mergeBuildInNameToPattern(pattern string, structName, methodName string) 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)
|
||||
}
|
||||
// 检测域名后缀
|
||||
array := strings.Split(pattern, "@")
|
||||
// 分离URI(其实可能包含HTTP Method)
|
||||
uri := array[0]
|
||||
uri = strings.TrimRight(uri, "/") + "/" + methodName
|
||||
// 加上指定域名后缀
|
||||
if len(array) > 1 {
|
||||
return uri + "@" + array[1]
|
||||
}
|
||||
return uri
|
||||
}
|
||||
|
||||
// 将给定的名称转换为URL规范格式。
|
||||
// 规范1: 全部转换为小写;
|
||||
// 规范2: 方法名中间存在大写字母,转换为小写URI地址以“-”号链接每个单词;
|
||||
func (s *Server) nameToUrlPart(name string) string {
|
||||
part := ""
|
||||
for i := 0; i < len(name); i++ {
|
||||
if i > 0 && gstr.IsLetterUpper(name[i]) {
|
||||
part += "-"
|
||||
}
|
||||
part += string(name[i])
|
||||
}
|
||||
return strings.ToLower(part)
|
||||
}
|
105
g/net/ghttp/ghttp_server_service_object.go
Normal file
105
g/net/ghttp/ghttp_server_service_object.go
Normal file
@ -0,0 +1,105 @@
|
||||
// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
// 服务注册.
|
||||
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面
|
||||
// 需要注意对象方法的定义必须按照ghttp.HandlerFunc来定义
|
||||
func (s *Server)BindObject(pattern string, obj interface{}, methods...string) error {
|
||||
if len(methods) > 0 {
|
||||
return s.BindObjectMethod(pattern, obj, strings.Join(methods, ","))
|
||||
}
|
||||
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)
|
||||
m[key] = &handlerItem {
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : v.Method(i).Interface().(func(*Request)),
|
||||
}
|
||||
// 如果方法中带有Index方法,那么额外自动增加一个路由规则匹配主URI
|
||||
if strings.EqualFold(method, "Index") {
|
||||
p := key
|
||||
if strings.EqualFold(p[len(p) - 6:], "/index") {
|
||||
p = p[0 : len(p) - 6]
|
||||
}
|
||||
m[p] = &handlerItem {
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : v.Method(i).Interface().(func(*Request)),
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面
|
||||
// 第三个参数methods支持多个方法注册,多个方法以英文“,”号分隔,区分大小写
|
||||
func (s *Server)BindObjectMethod(pattern string, obj interface{}, methods 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)
|
||||
}
|
||||
key := s.mergeBuildInNameToPattern(pattern, sname, mname)
|
||||
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]
|
||||
}
|
||||
m[p] = &handlerItem {
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : fval.Interface().(func(*Request)),
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面
|
||||
// 需要注意对象方法的定义必须按照ghttp.HandlerFunc来定义
|
||||
func (s *Server)BindObjectRest(pattern string, obj interface{}) error {
|
||||
m := make(handlerMap)
|
||||
v := reflect.ValueOf(obj)
|
||||
t := v.Type()
|
||||
for i := 0; i < v.NumMethod(); i++ {
|
||||
name := t.Method(i).Name
|
||||
method := strings.ToUpper(name)
|
||||
if _, ok := s.methodsMap[method]; !ok {
|
||||
continue
|
||||
}
|
||||
key := name + ":" + pattern
|
||||
m[key] = &handlerItem {
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : v.Method(i).Interface().(func(*Request)),
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
@ -13,12 +13,17 @@ import (
|
||||
"encoding/json"
|
||||
"gitee.com/johng/gf/g/util/gstr"
|
||||
"gitee.com/johng/gf/g/util/gconv"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// 格式化打印变量(类似于PHP-vardump)
|
||||
func Dump(i interface{}) {
|
||||
if b, err := json.MarshalIndent(i, "", "\t"); err == nil {
|
||||
fmt.Println(string(b))
|
||||
buffer := &bytes.Buffer{}
|
||||
encoder := json.NewEncoder(buffer)
|
||||
encoder.SetEscapeHTML(false)
|
||||
encoder.SetIndent("", "\t")
|
||||
if err := encoder.Encode(i); err == nil {
|
||||
fmt.Println(buffer.String())
|
||||
} else {
|
||||
fmt.Errorf("%s\n", err.Error())
|
||||
}
|
||||
|
@ -13,10 +13,6 @@ func init() {
|
||||
g.Server().BindController("/{.struct}/{.method}", &Order{})
|
||||
}
|
||||
|
||||
func (o *Order) Index() {
|
||||
o.Response.Write("Order Index")
|
||||
}
|
||||
|
||||
func (o *Order) List() {
|
||||
o.Response.Write("Order List")
|
||||
o.Response.Write("List")
|
||||
}
|
||||
|
@ -1,27 +1,27 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/net/ghttp"
|
||||
"gitee.com/johng/gf/g"
|
||||
"gitee.com/johng/gf/g/frame/gmvc"
|
||||
)
|
||||
|
||||
type ControllerMethod struct {
|
||||
type Method struct {
|
||||
gmvc.Controller
|
||||
}
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindControllerMethod("/method", &ControllerMethod{}, "Name, Age")
|
||||
g.Server().BindControllerMethod("/method", &Method{}, "Name, Age")
|
||||
}
|
||||
|
||||
func (c *ControllerMethod) Name() {
|
||||
func (c *Method) Name() {
|
||||
c.Response.Write("John")
|
||||
}
|
||||
|
||||
func (c *ControllerMethod) Age() {
|
||||
func (c *Method) Age() {
|
||||
c.Response.Write("18")
|
||||
}
|
||||
|
||||
func (c *ControllerMethod) Info() {
|
||||
func (c *Method) Info() {
|
||||
c.Response.Write("Info")
|
||||
}
|
||||
|
||||
|
@ -1,38 +1,35 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/net/ghttp"
|
||||
"gitee.com/johng/gf/g"
|
||||
"gitee.com/johng/gf/g/frame/gmvc"
|
||||
)
|
||||
|
||||
// 测试控制器
|
||||
type ControllerRest struct {
|
||||
type Rest struct {
|
||||
gmvc.Controller
|
||||
}
|
||||
|
||||
// 初始化控制器对象,并绑定操作到Web Server
|
||||
func init() {
|
||||
// 控制器公开方法中与HTTP Method方法同名的方法将会自动绑定映射
|
||||
ghttp.GetServer().BindControllerRest("/john", &ControllerRest{})
|
||||
g.Server().BindControllerRest("/rest", &Rest{})
|
||||
}
|
||||
|
||||
// RESTFul - GET
|
||||
func (c *ControllerRest) Get() {
|
||||
func (c *Rest) Get() {
|
||||
c.Response.Write("RESTFul HTTP Method GET")
|
||||
}
|
||||
|
||||
// RESTFul - POST
|
||||
func (c *ControllerRest) Post() {
|
||||
func (c *Rest) Post() {
|
||||
c.Response.Write("RESTFul HTTP Method POST")
|
||||
}
|
||||
|
||||
// RESTFul - DELETE
|
||||
func (c *ControllerRest) Delete() {
|
||||
func (c *Rest) Delete() {
|
||||
c.Response.Write("RESTFul HTTP Method DELETE")
|
||||
}
|
||||
|
||||
// 该方法无法映射,将会无法访问到
|
||||
func (c *ControllerRest) Hello() {
|
||||
func (c *Rest) Hello() {
|
||||
c.Response.Write("Hello")
|
||||
}
|
||||
|
||||
|
@ -1,43 +1,33 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/net/ghttp"
|
||||
"gitee.com/johng/gf/g"
|
||||
"gitee.com/johng/gf/g/frame/gmvc"
|
||||
)
|
||||
|
||||
// 定义业务相关的控制器对象,
|
||||
// 建议命名规范中控制器统一使用Controller前缀,后期代码维护时便于区分
|
||||
type ControllerUser struct {
|
||||
type User struct {
|
||||
gmvc.Controller
|
||||
}
|
||||
|
||||
// 初始化控制器对象,并绑定操作到Web Server
|
||||
func init() {
|
||||
// 绑定控制器到指定URI,所有控制器的公开方法将会映射到指定URI末尾
|
||||
// 例如该方法执行后,查看效果可访问:
|
||||
// http://127.0.0.1:8199/user/name
|
||||
// http://127.0.0.1:8199/user/age
|
||||
// http://127.0.0.1:8199/user/true-name
|
||||
ghttp.GetServer().BindController("/user", &ControllerUser{})
|
||||
s := g.Server()
|
||||
s.BindController("/user", new(User))
|
||||
s.BindController("/user/{.method}/{uid}", new(User), "Info")
|
||||
s.BindController("/user/{.method}/{page}.html", new(User), "List")
|
||||
}
|
||||
|
||||
// 定义操作逻辑 - 展示姓名
|
||||
func (c *ControllerUser) Name() {
|
||||
c.Response.Write("John")
|
||||
func (u *User) Index() {
|
||||
u.Response.Write("User")
|
||||
}
|
||||
|
||||
// 定义操作逻辑 - 展示年龄
|
||||
func (c *ControllerUser) Age() {
|
||||
c.Response.Write("18")
|
||||
func (u *User) Info() {
|
||||
u.Response.Write("Info - Uid: ", u.Request.Get("uid"))
|
||||
}
|
||||
|
||||
// 定义操作逻辑 - 展示方法名称如果带多个单词,路由控制器使用英文连接符号"-"进行拼接
|
||||
func (c *ControllerUser) TrueName() {
|
||||
c.View.Assigns(map[string]interface{}{
|
||||
|
||||
})
|
||||
c.Response.Write("John Smith")
|
||||
func (u *User) List() {
|
||||
u.Response.Write("List - Page: ", u.Request.Get("page"))
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -10,14 +10,14 @@ func main() {
|
||||
s := g.Server()
|
||||
|
||||
// 多事件回调示例,事件1
|
||||
pattern1 := "/:name/info/{uid}"
|
||||
pattern1 := "/:name/info"
|
||||
s.BindHookHandlerByMap(pattern1, map[string]ghttp.HandlerFunc {
|
||||
"BeforeServe" : func(r *ghttp.Request) {
|
||||
fmt.Println("打印到Server端终端")
|
||||
r.SetQuery("uid", "1000")
|
||||
},
|
||||
})
|
||||
s.BindHandler(pattern1, func(r *ghttp.Request) {
|
||||
r.Response.Write("用户:", r.Get("name"), ", uid:", r.Get("uid"))
|
||||
r.Response.Write("用户:", r.Get("name"), ", uid:", r.GetQueryString("uid"))
|
||||
})
|
||||
|
||||
// 多事件回调示例,事件2
|
||||
|
Loading…
Reference in New Issue
Block a user