diff --git a/g/net/ghttp/http_server.go b/g/net/ghttp/http_server.go index ad1a7b650..1da5ea53e 100644 --- a/g/net/ghttp/http_server.go +++ b/g/net/ghttp/http_server.go @@ -19,10 +19,10 @@ import ( "path/filepath" "gitee.com/johng/gf/g/util/gutil" "gitee.com/johng/gf/g/net/grouter" - "gitee.com/johng/gf/g/util/gidgen" "gitee.com/johng/gf/g/container/gmap" "gitee.com/johng/gf/g/container/gqueue" "gitee.com/johng/gf/g/container/glist" + "gitee.com/johng/gf/g/container/gtype" ) const ( @@ -41,7 +41,7 @@ type Server struct { status int8 // 当前服务器状态(0:未启动,1:运行中) handlerMap HandlerMap // 所有注册的回调函数 methodsMap map[string]bool // 所有支持的HTTP Method(初始化时自动填充) - idgen *gidgen.Gen // 请求ID生成器 + servedCount *gtype.Int // 已经服务的请求数(4-8字节,不考虑溢出情况) closeQueue *gqueue.Queue // 请求结束的关闭队列(存放的是需要异步关闭处理的*Request对象) hooksMap *gmap.StringInterfaceMap // 钩子注册方法map,键值为按照注册顺序生成的glist,用于hook顺序调用 Router *grouter.Router // 路由管理对象 @@ -77,7 +77,7 @@ func GetServer(names...string) (*Server) { name : name, handlerMap : make(HandlerMap), methodsMap : make(map[string]bool), - idgen : gidgen.New(50000), + servedCount : gtype.NewInt(), closeQueue : gqueue.New(), hooksMap : gmap.NewStringInterfaceMap(), Router : grouter.New(), @@ -492,6 +492,16 @@ func (s *Server)BindHookHandler(pattern string, hook string, handler HandlerFunc return nil } +// 通过map批量绑定回调函数 +func (s *Server)BindHookHandlerByMap(pattern string, hookmap map[string]HandlerFunc) error { + for k, v := range hookmap { + if err := s.BindHookHandler(pattern, k, v); err != nil { + return err + } + } + return nil +} + //// 绑定URI服务注册的Init回调函数,回调时按照注册顺序执行 //// Init回调调用时机为请求进入控制器之前,初始化Request对象之后 //func (s *Server)BindHookHandlerInit(pattern string, handler HandlerFunc) error { diff --git a/g/net/ghttp/http_server_auto.go b/g/net/ghttp/http_server_auto.go index 3db2d0ced..3904816ff 100644 --- a/g/net/ghttp/http_server_auto.go +++ b/g/net/ghttp/http_server_auto.go @@ -12,10 +12,14 @@ func (s *Server) startCloseQueueLoop() { for { if v := s.closeQueue.PopFront(); v != nil { r := v.(*Request) + s.callHookHandler(r, "BeforeRequestClose") + // 关闭当前会话的Cookie r.Cookie.Close() - // 更新Sssion会话超时时间 + // 更新Session会话超时时间 r.Session.UpdateExpire() + + s.callHookHandler(r, "AfterRequestClose") } } }() diff --git a/g/net/ghttp/http_server_domain.go b/g/net/ghttp/http_server_domain.go index b733275ef..7bae5868a 100644 --- a/g/net/ghttp/http_server_domain.go +++ b/g/net/ghttp/http_server_domain.go @@ -119,6 +119,16 @@ func (d *Domain)BindHookHandler(pattern string, hook string, handler HandlerFunc return nil } +// 通过map批量绑定回调函数 +func (d *Domain)BindHookHandlerByMap(pattern string, hookmap map[string]HandlerFunc) error { + for domain, _ := range d.m { + if err := d.s.BindHookHandlerByMap(pattern + "@" + domain, hookmap); err != nil { + return err + } + } + return nil +} + //// 绑定URI服务注册的Init回调函数,回调时按照注册顺序执行 //// Init回调调用时机为请求进入控制器之前,初始化Request对象之后 //func (d *Domain)BindHookHandlerInit(pattern string, handler HandlerFunc) error { diff --git a/g/net/ghttp/http_server_handler.go b/g/net/ghttp/http_server_handler.go index 208ccd845..0dfa1a93d 100644 --- a/g/net/ghttp/http_server_handler.go +++ b/g/net/ghttp/http_server_handler.go @@ -38,7 +38,7 @@ func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) { } // 构造请求参数对象 request := &Request{ - Id : s.idgen.Int(), + Id : s.servedCount.Add(1), Server : s, Request : *r, Response : &Response { @@ -89,7 +89,9 @@ func (s *Server)callHandler(h *HandlerItem, r *Request) { s.callHookHandler(r, "AfterCookieOutput") // 输出缓冲区 + s.callHookHandler(r, "BeforeBufferOutput") r.Response.OutputBuffer() + s.callHookHandler(r, "AfterBufferOutput") // 将Request对象指针丢到队列中异步处理 s.closeQueue.PushBack(r) diff --git a/g/os/gtime/time_test.go b/g/os/gtime/time_test.go new file mode 100644 index 000000000..1bf4daf53 --- /dev/null +++ b/g/os/gtime/time_test.go @@ -0,0 +1,18 @@ +// Copyright 2017 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 gtime_test + +import ( + "testing" + "gitee.com/johng/gf/g/os/gtime" +) + +func BenchmarkNanosecond(b *testing.B) { + for i := 0; i < b.N; i++ { + gtime.Nanosecond() + } +} \ No newline at end of file diff --git a/g/util/gidgen/gidgen.go b/g/util/gidgen/gidgen.go deleted file mode 100644 index 97f99c772..000000000 --- a/g/util/gidgen/gidgen.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2017 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. - -// ID生成器. -// 内部采用了通道+缓冲池来实现高效的ID递增生成, -// 非常适合高并发下使用 -package gidgen - -import "math" - -// ID生成器管理对象 -type Gen struct { - ch chan uint - closeQueue chan struct{} -} - -// 创建一个ID生成器,并给定ID池大小 -func New (bufsize int) *Gen { - g := &Gen { - ch : make(chan uint, bufsize), - closeQueue : make(chan struct{}), - } - go g.startLoop() - return g -} - -// 关闭生成器 -func (g *Gen) Close() { - close(g.closeQueue) - close(g.ch) -} - -// 内部循环,当最大值使用完之后重新从1开始获取 -func (g *Gen) startLoop() { - for { - select { - case <- g.closeQueue: - return - default: - // 当ch达到缓冲池大小,会阻塞,只要有线程取出值,再立即填充 - for i := uint(1); i < uint(math.MaxUint64); i++ { - g.ch <- i - } - } - } -} - -// 从池中获取一个ID返回(uint) -func (g *Gen) Uint() uint { - return <- g.ch -} - -// 从池中获取一个ID返回(int) -func (g *Gen) Int() int { - i := <- g.ch - if i != 0 { - i = i & 0x7FFFFFFFFFFFFFFF - // 可能是int与uint之间的临界点 - if i == 0 { - return g.Int() - } - } - return int(i) -} - diff --git a/geg/net/ghttp/events.go b/geg/net/ghttp/events.go new file mode 100644 index 000000000..b37c0ad10 --- /dev/null +++ b/geg/net/ghttp/events.go @@ -0,0 +1,29 @@ +package main + +import ( + "gitee.com/johng/gf/g/net/ghttp" + "fmt" +) + +func main() { + pattern := "/" + ghttp.GetServer().BindHookHandlerByMap(pattern, map[string]ghttp.HandlerFunc{ + "BeforeServe" : func(r *ghttp.Request){ fmt.Println("BeforeServe") }, + "AfterServe" : func(r *ghttp.Request){ fmt.Println("AfterServe") }, + "BeforeRouterPatch" : func(r *ghttp.Request){ fmt.Println("BeforeRouterPatch") }, + "AfterRouterPatch" : func(r *ghttp.Request){ fmt.Println("AfterRouterPatch") }, + "BeforeCookieOutput" : func(r *ghttp.Request){ fmt.Println("BeforeCookieOutput") }, + "AfterCookieOutput" : func(r *ghttp.Request){ fmt.Println("AfterCookieOutput") }, + "BeforeBufferOutput" : func(r *ghttp.Request){ fmt.Println("BeforeBufferOutput") }, + "AfterBufferOutput" : func(r *ghttp.Request){ fmt.Println("AfterBufferOutput") }, + "BeforeRequestClose" : func(r *ghttp.Request){ fmt.Println("BeforeRequestClose") }, + "AfterRequestClose" : func(r *ghttp.Request){ fmt.Println("AfterRequestClose") }, + }) + ghttp.GetServer().BindHandler(pattern, func(r *ghttp.Request) { + r.Response.WriteString("Hello World!") + }) + ghttp.GetServer().SetPort(10000) + ghttp.GetServer().Run() + + select { } +} \ No newline at end of file diff --git a/geg/other/test.go b/geg/other/test.go index 4bed28c4b..974cd0ad5 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,56 +1,10 @@ package main import ( - "gitee.com/johng/gf/g/database/gdb" "fmt" + "math" ) -type Model struct { - TableName string -} - -var Db *gdb.Db - -func init() { - gdb.AddDefaultConfigNode(gdb.ConfigNode { - Host : "127.0.0.1", - Port : "3306", - User : "root", - Pass : "123456", - Name : "test", - Type : "mysql", - Role : "master", - Charset : "utf8", - }) - var err error - Db, err = gdb.Instance() - checkErr(err) -} - -func checkErr(err error) { - if err != nil { - panic(err) - } -} - -type UserModel struct { - Model -} - -func (u *UserModel) Get() (user gdb.Map){ - user, _ = Db.Table("user").Fields("uid, nickname, email").Where("uid = ?", 15).One() - return -} - -func (u *UserModel) Insert(data gdb.Map) (id int64) { - ret, _ := Db.Table("user").Data(data).Insert() - id, _ = ret.LastInsertId() - return -} - func main() { - u := &UserModel{} - user := u.Get() - fmt.Println(user) - u.Insert(gdb.Map{"uid": 100, "name": "jack"}) + fmt.Println(math.MaxInt64) } \ No newline at end of file