mirror of
https://gitee.com/johng/gf
synced 2026-06-07 10:22:11 +08:00
改进ghttp server方法注册设计
This commit is contained in:
@ -174,7 +174,7 @@ func (r *ClientRequest) GetRaw() string {
|
||||
func (r *ClientRequest) GetJson() *gjson.Json {
|
||||
data := r.GetRaw()
|
||||
if data != "" {
|
||||
if j, err := gjson.DecodeToJson(data); err == nil {
|
||||
if j, err := gjson.DecodeToJson([]byte(data)); err == nil {
|
||||
return j
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,14 +31,18 @@ type Server struct {
|
||||
}
|
||||
|
||||
// 域名、URI与回调函数的绑定记录表
|
||||
type HandlerMap map[string]HandlerFunc
|
||||
type HandlerMap map[string]HandlerItem
|
||||
|
||||
// http回调函数注册信息
|
||||
type HandlerFunc struct {
|
||||
type HandlerItem struct {
|
||||
ctype reflect.Type // 控制器类型
|
||||
fname string // 回调方法名称
|
||||
faddr HandlerFunc // 准确的执行方法内存地址(与以上两个参数二选一)
|
||||
}
|
||||
|
||||
// http注册函数
|
||||
type HandlerFunc func(*Server, *ClientRequest, *ServerResponse)
|
||||
|
||||
// Server表,用以存储和检索名称与Server对象之间的关联关系
|
||||
var serverMapping = gmap.NewStringInterfaceMap()
|
||||
|
||||
@ -226,26 +230,26 @@ func (s *Server) handlerKey(domain, method, pattern string) string {
|
||||
}
|
||||
|
||||
// 设置请求处理方法
|
||||
func (s *Server) setHandler(domain, method, pattern string, handler HandlerFunc) {
|
||||
func (s *Server) setHandler(domain, method, pattern string, hitem HandlerItem) {
|
||||
s.hmu.Lock()
|
||||
defer s.hmu.Unlock()
|
||||
if method == gDEFAULT_METHOD {
|
||||
s.handlerMap[s.handlerKey(domain, "GET", pattern)] = handler
|
||||
s.handlerMap[s.handlerKey(domain, "PUT", pattern)] = handler
|
||||
s.handlerMap[s.handlerKey(domain, "POST", pattern)] = handler
|
||||
s.handlerMap[s.handlerKey(domain, "DELETE", pattern)] = handler
|
||||
s.handlerMap[s.handlerKey(domain, "PATCH", pattern)] = handler
|
||||
s.handlerMap[s.handlerKey(domain, "HEAD", pattern)] = handler
|
||||
s.handlerMap[s.handlerKey(domain, "CONNECT", pattern)] = handler
|
||||
s.handlerMap[s.handlerKey(domain, "OPTIONS", pattern)] = handler
|
||||
s.handlerMap[s.handlerKey(domain, "TRACE", pattern)] = handler
|
||||
s.handlerMap[s.handlerKey(domain, "GET", pattern)] = hitem
|
||||
s.handlerMap[s.handlerKey(domain, "PUT", pattern)] = hitem
|
||||
s.handlerMap[s.handlerKey(domain, "POST", pattern)] = hitem
|
||||
s.handlerMap[s.handlerKey(domain, "DELETE", pattern)] = hitem
|
||||
s.handlerMap[s.handlerKey(domain, "PATCH", pattern)] = hitem
|
||||
s.handlerMap[s.handlerKey(domain, "HEAD", pattern)] = hitem
|
||||
s.handlerMap[s.handlerKey(domain, "CONNECT", pattern)] = hitem
|
||||
s.handlerMap[s.handlerKey(domain, "OPTIONS", pattern)] = hitem
|
||||
s.handlerMap[s.handlerKey(domain, "TRACE", pattern)] = hitem
|
||||
} else {
|
||||
s.handlerMap[s.handlerKey(domain, method, pattern)] = handler
|
||||
s.handlerMap[s.handlerKey(domain, method, pattern)] = hitem
|
||||
}
|
||||
}
|
||||
|
||||
// 查询请求处理方法
|
||||
func (s *Server) getHandler(domain, method, pattern string) *HandlerFunc {
|
||||
func (s *Server) getHandler(domain, method, pattern string) *HandlerItem {
|
||||
s.hmu.RLock()
|
||||
defer s.hmu.RUnlock()
|
||||
key := s.handlerKey(domain, method, pattern)
|
||||
@ -258,7 +262,7 @@ func (s *Server) getHandler(domain, method, pattern string) *HandlerFunc {
|
||||
// 绑定URI到操作函数/方法
|
||||
// pattern的格式形如:/user/list, put:/user, delete:/user, post:/user@johng.cn
|
||||
// 支持RESTful的请求格式,具体业务逻辑由绑定的处理方法来执行
|
||||
func (s *Server)bindHandler(pattern string, handler HandlerFunc) error {
|
||||
func (s *Server)bindHandlerItem(pattern string, hitem HandlerItem) error {
|
||||
if s.status == 1 {
|
||||
return errors.New("server handlers cannot be changed while running")
|
||||
}
|
||||
@ -279,27 +283,27 @@ func (s *Server)bindHandler(pattern string, handler HandlerFunc) error {
|
||||
if uri == "" {
|
||||
return errors.New("invalid pattern")
|
||||
}
|
||||
s.setHandler(domain, method, uri, handler)
|
||||
s.setHandler(domain, method, uri, hitem)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 通过映射数组绑定URI到操作函数/方法
|
||||
func (s *Server)bindHandlerByMap(m HandlerMap) error {
|
||||
for p, h := range m {
|
||||
if err := s.bindHandler(p, h); err != nil {
|
||||
if err := s.bindHandlerItem(p, h); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 绑定方法,pattern支持http method
|
||||
// pattern的格式形如:/user/list, put:/user, delete:/user
|
||||
func (s *Server)BindMethod(pattern string, c Controller, method string) error {
|
||||
return s.bindHandler(pattern, HandlerFunc{reflect.ValueOf(c).Elem().Type(), method})
|
||||
// 注意该方法是直接绑定方法的内存地址,执行的时候直接执行该方法,不会存在初始化新的控制器逻辑
|
||||
func (s *Server)BindHandler(pattern string, handler HandlerFunc) error {
|
||||
return s.bindHandlerItem(pattern, HandlerItem{nil, "", handler})
|
||||
}
|
||||
|
||||
// 绑定控制器,控制器需要实现gmvc.Controller接口
|
||||
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
|
||||
func (s *Server)BindController(uri string, c Controller) error {
|
||||
// 遍历控制器,获取方法列表,并构造成uri
|
||||
m := make(HandlerMap)
|
||||
@ -317,7 +321,14 @@ func (s *Server)BindController(uri string, c Controller) error {
|
||||
}
|
||||
key += strings.ToLower(string(name[i]))
|
||||
}
|
||||
m[key] = HandlerFunc{v.Elem().Type(), name}
|
||||
m[key] = HandlerItem{v.Elem().Type(), name, nil}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
// 绑定方法,pattern支持http method
|
||||
// pattern的格式形如:/user/list, put:/user, delete:/user
|
||||
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
|
||||
func (s *Server)BindControllerMethod(pattern string, c Controller, method string) error {
|
||||
return s.bindHandlerItem(pattern, HandlerItem{reflect.ValueOf(c).Elem().Type(), method, nil})
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@ import (
|
||||
"crypto/tls"
|
||||
"time"
|
||||
"log"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
)
|
||||
|
||||
// HTTP Server 设置结构体
|
||||
@ -37,7 +36,7 @@ var defaultServerConfig = ServerConfig {
|
||||
IndexFiles : []string{"index.html", "index.htm"},
|
||||
IndexFolder : false,
|
||||
ServerAgent : "gf",
|
||||
ServerRoot : gfile.SelfDir(),
|
||||
ServerRoot : "",
|
||||
}
|
||||
|
||||
// 获取默认的http server设置
|
||||
|
||||
@ -32,8 +32,8 @@ func (s *Server) Domain(domain string) *Domain {
|
||||
}
|
||||
|
||||
// 绑定方法
|
||||
func (d *Domain) BindMethod(pattern string, c Controller, method string) error {
|
||||
return d.s.BindMethod(pattern, c, method)
|
||||
func (d *Domain) BindControllerMethod(pattern string, c Controller, method string) error {
|
||||
return d.s.BindControllerMethod(pattern, c, method)
|
||||
}
|
||||
|
||||
// 绑定控制器
|
||||
|
||||
@ -28,10 +28,10 @@ func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
request.Request = *r
|
||||
response.ResponseWriter = w
|
||||
if h := s.getHandler(gDEFAULT_DOMAIN, r.Method, r.URL.Path); h != nil {
|
||||
s.initController(h, request, response)
|
||||
s.callHandler(h, request, response)
|
||||
} else {
|
||||
if h := s.getHandler(strings.Split(r.Host, ":")[0], r.Method, r.URL.Path); h != nil {
|
||||
s.initController(h, request, response)
|
||||
s.callHandler(h, request, response)
|
||||
} else {
|
||||
s.serveFile(w, r)
|
||||
}
|
||||
@ -39,11 +39,15 @@ func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// 初始化控制器
|
||||
func (s *Server)initController(h *HandlerFunc, r *ClientRequest, w *ServerResponse) {
|
||||
c := reflect.New(h.ctype)
|
||||
c.MethodByName("Init").Call([]reflect.Value{reflect.ValueOf(s), reflect.ValueOf(r), reflect.ValueOf(w)})
|
||||
c.MethodByName(h.fname).Call(nil)
|
||||
c.MethodByName("Shut").Call(nil)
|
||||
func (s *Server)callHandler(h *HandlerItem, r *ClientRequest, w *ServerResponse) {
|
||||
if h.faddr == nil {
|
||||
c := reflect.New(h.ctype)
|
||||
c.MethodByName("Init").Call([]reflect.Value{reflect.ValueOf(s), reflect.ValueOf(r), reflect.ValueOf(w)})
|
||||
c.MethodByName(h.fname).Call(nil)
|
||||
c.MethodByName("Shut").Call(nil)
|
||||
} else {
|
||||
h.faddr(s, r, w)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理静态文件请求
|
||||
|
||||
@ -52,6 +52,13 @@ func (r *ServerResponse) WriteHeaderEncoding(encoding string) {
|
||||
r.Header().Set("Content-Type", "text/plain; charset=" + encoding)
|
||||
}
|
||||
|
||||
// 获取缓冲区数据
|
||||
func (r *ServerResponse) Buffer() []byte {
|
||||
r.bufmu.RLock()
|
||||
defer r.bufmu.RUnlock()
|
||||
return r.buffer
|
||||
}
|
||||
|
||||
// 输出缓冲区数据到客户端
|
||||
func (r *ServerResponse) Output() {
|
||||
r.bufmu.RLock()
|
||||
|
||||
@ -3,7 +3,6 @@ package user
|
||||
import (
|
||||
"gitee.com/johng/gf/g/net/ghttp"
|
||||
"gitee.com/johng/gf/g/frame/gmvc"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 定义业务相关的控制器对象
|
||||
@ -11,21 +10,23 @@ type ControllerUser struct {
|
||||
gmvc.Controller
|
||||
}
|
||||
|
||||
func Add(i1, i2 int) int {
|
||||
return i1 + i2
|
||||
func Test(s *ghttp.Server, r *ghttp.ClientRequest, w *ghttp.ServerResponse) {
|
||||
w.WriteString("Test")
|
||||
w.Output()
|
||||
}
|
||||
|
||||
// 初始化控制器对象,并绑定操作到Web Server
|
||||
func init() {
|
||||
//ghttp.GetServer("johng").Domain("localhost").BindHandler("/user", u.Info)
|
||||
ghttp.GetServer("johng").BindHandler("/test", Test)
|
||||
ghttp.GetServer("johng").BindController("/user", &ControllerUser{})
|
||||
}
|
||||
|
||||
// 定义操作逻辑
|
||||
func (c *ControllerUser) Info() {
|
||||
fmt.Println(c.Db)
|
||||
c.View.Assign("name", "john")
|
||||
c.View.Display("user/index")
|
||||
c.Response.WriteString("hello world!")
|
||||
//c.View.Assign("name", "john")
|
||||
//c.View.Display("user/index")
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user