ghttp增加Init&Shut回调函数注册功能,gmap增加SetWithDefault方法

This commit is contained in:
John
2018-03-13 17:57:41 +08:00
parent 1f78e1602b
commit 2ff5698845
18 changed files with 337 additions and 47 deletions

View File

@ -59,13 +59,25 @@ func (this *IntBoolMap) BatchSet(m map[int]bool) {
}
// 获取键值
func (this *IntBoolMap) Get(key int) (bool) {
func (this *IntBoolMap) Get(key int) bool {
this.mu.RLock()
val, _ := this.m[key]
this.mu.RUnlock()
return val
}
// 获取键值,如果键值不存在则写入默认值
func (this *IntBoolMap) GetWithDefault(key int, value bool) bool {
this.mu.Lock()
val, ok := this.m[key]
if !ok {
this.m[key] = value
val = value
}
this.mu.Unlock()
return val
}
// 删除键值对
func (this *IntBoolMap) Remove(key int) {
this.mu.Lock()

View File

@ -66,6 +66,18 @@ func (this *IntIntMap) Get(key int) (int) {
return val
}
// 获取键值,如果键值不存在则写入默认值
func (this *IntIntMap) GetWithDefault(key int, value int) int {
this.mu.Lock()
val, ok := this.m[key]
if !ok {
this.m[key] = value
val = value
}
this.mu.Unlock()
return val
}
// 删除键值对
func (this *IntIntMap) Remove(key int) {
this.mu.Lock()

View File

@ -67,6 +67,18 @@ func (this *IntInterfaceMap) Get(key int) (interface{}) {
return val
}
// 获取键值,如果键值不存在则写入默认值
func (this *IntInterfaceMap) GetWithDefault(key int, value interface{}) interface{} {
this.mu.Lock()
val, ok := this.m[key]
if !ok {
this.m[key] = value
val = value
}
this.mu.Unlock()
return val
}
func (this *IntInterfaceMap) GetBool(key int) bool {
return gconv.Bool(this.Get(key))
}

View File

@ -59,13 +59,25 @@ func (this *IntStringMap) BatchSet(m map[int]string) {
}
// 获取键值
func (this *IntStringMap) Get(key int) (string) {
func (this *IntStringMap) Get(key int) string {
this.mu.RLock()
val, _ := this.m[key]
this.mu.RUnlock()
return val
}
// 获取键值,如果键值不存在则写入默认值
func (this *IntStringMap) GetWithDefault(key int, value string) string {
this.mu.Lock()
val, ok := this.m[key]
if !ok {
this.m[key] = value
val = value
}
this.mu.Unlock()
return val
}
// 删除键值对
func (this *IntStringMap) Remove(key int) {
this.mu.Lock()

View File

@ -60,13 +60,25 @@ func (this *InterfaceInterfaceMap) BatchSet(m map[interface{}]interface{}) {
}
// 获取键值
func (this *InterfaceInterfaceMap) Get(key interface{}) (interface{}) {
func (this *InterfaceInterfaceMap) Get(key interface{}) interface{} {
this.mu.RLock()
val, _ := this.m[key]
this.mu.RUnlock()
return val
}
// 获取键值,如果键值不存在则写入默认值
func (this *InterfaceInterfaceMap) GetWithDefault(key interface{}, value interface{}) interface{} {
this.mu.Lock()
val, ok := this.m[key]
if !ok {
this.m[key] = value
val = value
}
this.mu.Unlock()
return val
}
func (this *InterfaceInterfaceMap) GetBool(key interface{}) bool {
return gconv.Bool(this.Get(key))
}

View File

@ -59,13 +59,25 @@ func (this *StringBoolMap) BatchSet(m map[string]bool) {
}
// 获取键值
func (this *StringBoolMap) Get(key string) (bool) {
func (this *StringBoolMap) Get(key string) bool {
this.mu.RLock()
val, _ := this.m[key]
this.mu.RUnlock()
return val
}
// 获取键值,如果键值不存在则写入默认值
func (this *StringBoolMap) GetWithDefault(key string, value bool) bool {
this.mu.Lock()
val, ok := this.m[key]
if !ok {
this.m[key] = value
val = value
}
this.mu.Unlock()
return val
}
// 删除键值对
func (this *StringBoolMap) Remove(key string) {
this.mu.Lock()

View File

@ -59,13 +59,25 @@ func (this *StringIntMap) BatchSet(m map[string]int) {
}
// 获取键值
func (this *StringIntMap) Get(key string) (int) {
func (this *StringIntMap) Get(key string) int {
this.mu.RLock()
val, _ := this.m[key]
this.mu.RUnlock()
return val
}
// 获取键值,如果键值不存在则写入默认值
func (this *StringIntMap) GetWithDefault(key string, value int) int {
this.mu.Lock()
val, ok := this.m[key]
if !ok {
this.m[key] = value
val = value
}
this.mu.Unlock()
return val
}
// 删除键值对
func (this *StringIntMap) Remove(key string) {
this.mu.Lock()

View File

@ -67,6 +67,18 @@ func (this *StringInterfaceMap) Get(key string) interface{} {
return val
}
// 获取键值,如果键值不存在则写入默认值
func (this *StringInterfaceMap) GetWithDefault(key string, value interface{}) interface{} {
this.mu.Lock()
val, ok := this.m[key]
if !ok {
this.m[key] = value
val = value
}
this.mu.Unlock()
return val
}
func (this *StringInterfaceMap) GetBool(key string) bool {
return gconv.Bool(this.Get(key))
}

View File

@ -66,6 +66,18 @@ func (this *StringStringMap) Get(key string) string {
return val
}
// 获取键值,如果键值不存在则写入默认值
func (this *StringStringMap) GetWithDefault(key string, value string) string {
this.mu.Lock()
val, ok := this.m[key]
if !ok {
this.m[key] = value
val = value
}
this.mu.Unlock()
return val
}
// 删除键值对
func (this *StringStringMap) Remove(key string) {
this.mu.Lock()

View File

@ -59,13 +59,25 @@ func (this *UintInterfaceMap) BatchSet(m map[uint]interface{}) {
}
// 获取键值
func (this *UintInterfaceMap) Get(key uint) (interface{}) {
func (this *UintInterfaceMap) Get(key uint) interface{} {
this.mu.RLock()
val, _ := this.m[key]
this.mu.RUnlock()
return val
}
// 获取键值,如果键值不存在则写入默认值
func (this *UintInterfaceMap) GetWithDefault(key uint, value interface{}) interface{} {
this.mu.Lock()
val, ok := this.m[key]
if !ok {
this.m[key] = value
val = value
}
this.mu.Unlock()
return val
}
func (this *UintInterfaceMap) GetBool(key uint) bool {
return gconv.Bool(this.Get(key))
}

View File

@ -32,7 +32,7 @@ func (c *Controller) Init(r *ghttp.Request) {
}
// 控制器结束请求接口方法
func (c *Controller) Shut() {
func (c *Controller) Shut(r *ghttp.Request) {
}

View File

@ -10,5 +10,5 @@ package ghttp
// 控制器接口
type Controller interface {
Init(*Request)
Shut()
Shut(*Request)
}

View File

@ -22,6 +22,7 @@ import (
"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"
)
const (
@ -33,16 +34,18 @@ const (
// http server结构体
type Server struct {
hmu sync.RWMutex // handlerMap互斥锁
name string // 服务名称,方便识别
server http.Server // 底层http server对象
config ServerConfig // 配置对象
status int8 // 当前服务器状态(0未启动1运行中)
handlerMap HandlerMap // 所有注册的回调函数
methodsMap map[string]bool // 所有支持的HTTP Method
idgen *gidgen.Gen // 请求ID生成器
closeQueue *gqueue.Queue // 请求结束的关闭队列(存放的是需要异步关闭处理的*Request对象)
Router *grouter.Router // 路由管理对象
hmu sync.RWMutex // handlerMap互斥锁
name string // 服务名称,方便识别
server http.Server // 底层http server对象
config ServerConfig // 配置对象
status int8 // 当前服务器状态(0未启动1运行中)
handlerMap HandlerMap // 所有注册的回调函数
methodsMap map[string]bool // 所有支持的HTTP Method(初始化时自动填充)
idgen *gidgen.Gen // 请求ID生成器
closeQueue *gqueue.Queue // 请求结束的关闭队列(存放的是需要异步关闭处理的*Request对象)
initHookMap *gmap.StringInterfaceMap // Init钩子注册方法map键值为按照注册顺序生成的glist用于hook顺序调用
shutHookMap *gmap.StringInterfaceMap // Shut钩子注册方法map键值为按照注册顺序生成的glist用于hook顺序调用
Router *grouter.Router // 路由管理对象
}
// 域名、URI与回调函数的绑定记录表
@ -72,12 +75,14 @@ func GetServer(names...string) (*Server) {
return s.(*Server)
}
s := &Server{
name : name,
handlerMap : make(HandlerMap),
methodsMap : make(map[string]bool),
idgen : gidgen.New(50000),
closeQueue : gqueue.New(),
Router : grouter.New(),
name : name,
handlerMap : make(HandlerMap),
methodsMap : make(map[string]bool),
idgen : gidgen.New(50000),
closeQueue : gqueue.New(),
initHookMap : gmap.NewStringInterfaceMap(),
shutHookMap : gmap.NewStringInterfaceMap(),
Router : grouter.New(),
}
for _, v := range strings.Split(gHTTP_METHODS, ",") {
s.methodsMap[v] = true
@ -259,15 +264,15 @@ func (s *Server) handlerKey(domain, method, pattern string) string {
}
// 设置请求处理方法
func (s *Server) setHandler(domain, method, pattern string, hitem HandlerItem) {
func (s *Server) setHandler(domain, method, pattern string, item HandlerItem) {
s.hmu.Lock()
defer s.hmu.Unlock()
if method == gDEFAULT_METHOD {
for v, _ := range s.methodsMap {
s.handlerMap[s.handlerKey(domain, v, pattern)] = hitem
s.handlerMap[s.handlerKey(domain, v, pattern)] = item
}
} else {
s.handlerMap[s.handlerKey(domain, method, pattern)] = hitem
s.handlerMap[s.handlerKey(domain, method, pattern)] = item
}
}
@ -283,16 +288,11 @@ func (s *Server) getHandler(domain, method, pattern string) *HandlerItem {
return nil
}
// 绑定URI到操作函数/方法
// pattern的格式形如/user/list, put:/user, delete:/user, post:/user@johng.cn
// 支持RESTful的请求格式具体业务逻辑由绑定的处理方法来执行
func (s *Server)bindHandlerItem(pattern string, hitem HandlerItem) error {
if s.status == 1 {
return errors.New("server handlers cannot be changed while running")
}
uri := ""
domain := gDEFAULT_DOMAIN
method := "all"
// 解析pattern
func (s *Server)parsePattern(pattern string) (domain, method, uri string, err error) {
uri = ""
domain = gDEFAULT_DOMAIN
method = "all"
result := strings.Split(pattern, "@")
if len(result) > 1 {
domain = result[1]
@ -305,9 +305,23 @@ func (s *Server)bindHandlerItem(pattern string, hitem HandlerItem) error {
uri = result[0]
}
if uri == "" {
err = errors.New("invalid pattern")
}
return
}
// 绑定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")
}
domain, method, uri, err := s.parsePattern(pattern)
if err != nil {
return errors.New("invalid pattern")
}
s.setHandler(domain, method, uri, hitem)
s.setHandler(domain, method, uri, item)
return nil
}
@ -362,7 +376,7 @@ func (s *Server)BindObject(pattern string, obj interface{}) error {
}
// 绑定对象到URI请求处理中会自动识别方法名称并附加到对应的URI地址后面
// 第三个参数methods支持多个方法注册多个方法以英文“,”号分隔
// 第三个参数methods支持多个方法注册多个方法以英文“,”号分隔,不区分大小写
func (s *Server)BindObjectMethod(pattern string, obj interface{}, methods string) error {
m := make(HandlerMap)
for _, v := range strings.Split(methods, ",") {
@ -440,7 +454,7 @@ func (s *Server)BindControllerRest(pattern string, c Controller) error {
}
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
// 第三个参数methods支持多个方法注册多个方法以英文“,”号分隔
// 第三个参数methods支持多个方法注册多个方法以英文“,”号分隔,不区分大小写
func (s *Server)BindControllerMethod(pattern string, c Controller, methods string) error {
m := make(HandlerMap)
cval := reflect.ValueOf(c)
@ -455,3 +469,85 @@ func (s *Server)BindControllerMethod(pattern string, c Controller, methods strin
}
return s.bindHandlerByMap(m)
}
// 绑定URI服务注册的Init回调函数回调时按照注册顺序执行
// Init回调调用时机为请求进入控制器之前初始化Request对象之后
func (s *Server)BindHookHandlerInit(pattern string, handler HandlerFunc) error {
domain, method, uri, err := s.parsePattern(pattern)
if err != nil {
return errors.New("invalid pattern")
}
var l *glist.List
if method == gDEFAULT_METHOD {
for v, _ := range s.methodsMap {
key := s.handlerKey(domain, v, uri)
if v := s.initHookMap.GetWithDefault(key, glist.New()); v != nil {
l = v.(*glist.List)
}
l.PushBack(handler)
}
} else {
key := s.handlerKey(domain, method, uri)
if v := s.initHookMap.GetWithDefault(key, glist.New()); v == nil {
l = v.(*glist.List)
}
l.PushBack(handler)
}
return nil
}
// 绑定URI服务注册的Shut回调函数回调时按照注册顺序执行
// Shut回调调用时机为请求执行完成之后所有的请求资源释放之前
func (s *Server)BindHookHandlerShut(pattern string, handler HandlerFunc) error {
domain, method, uri, err := s.parsePattern(pattern)
if err != nil {
return errors.New("invalid pattern")
}
var l *glist.List
if method == gDEFAULT_METHOD {
for v, _ := range s.methodsMap {
key := s.handlerKey(domain, v, uri)
if v := s.shutHookMap.GetWithDefault(key, glist.New()); v != nil {
l = v.(*glist.List)
}
l.PushBack(handler)
}
} else {
key := s.handlerKey(domain, method, uri)
if v := s.shutHookMap.GetWithDefault(key, glist.New()); v != nil {
l = v.(*glist.List)
}
l.PushBack(handler)
}
return nil
}
// 获取Init回调函数列表按照注册顺序排序
func (s *Server)getInitHookList(domain, method, uri string) []HandlerFunc {
key := s.handlerKey(domain, method, uri)
if v := s.initHookMap.Get(key); v != nil {
items := v.(*glist.List).FrontAll()
funcs := make([]HandlerFunc, len(items))
for k, v := range items {
funcs[k] = v.(HandlerFunc)
}
return funcs
}
return nil
}
// 获取Shut回调函数列表按照注册顺序排序
func (s *Server)getShutHookList(domain, method, uri string) []HandlerFunc {
key := s.handlerKey(domain, method, uri)
if v := s.shutHookMap.Get(key); v != nil {
items := v.(*glist.List).FrontAll()
funcs := make([]HandlerFunc, len(items))
for k, v := range items {
funcs[k] = v.(HandlerFunc)
}
return funcs
}
return nil
}

View File

@ -58,7 +58,7 @@ func (d *Domain) BindObject(pattern string, obj interface{}) error {
return nil
}
// 执行对象方法注册
// 执行对象方法注册methods参数不区分大小写
func (d *Domain) BindObjectMethod(pattern string, obj interface{}, methods string) error {
for domain, _ := range d.m {
if err := d.s.BindObjectMethod(pattern + "@" + domain, obj, methods); err != nil {
@ -98,7 +98,7 @@ func (d *Domain) BindControllerRest(pattern string, c Controller) error {
return nil
}
// 控制器方法注册
// 控制器方法注册methods参数不区分大小写
func (d *Domain) BindControllerMethod(pattern string, c Controller, methods string) error {
for domain, _ := range d.m {
if err := d.s.BindControllerMethod(pattern + "@" + domain, c, methods); err != nil {
@ -107,3 +107,25 @@ func (d *Domain) BindControllerMethod(pattern string, c Controller, methods stri
}
return nil
}
// 绑定URI服务注册的Init回调函数回调时按照注册顺序执行
// Init回调调用时机为请求进入控制器之前初始化Request对象之后
func (d *Domain)BindHookHandlerInit(pattern string, handler HandlerFunc) error {
for domain, _ := range d.m {
if err := d.s.BindHookHandlerInit(pattern + "@" + domain, handler); err != nil {
return err
}
}
return nil
}
// 绑定URI服务注册的Shut回调函数回调时按照注册顺序执行
// Shut回调调用时机为请求执行完成之后所有的请求资源释放之前
func (d *Domain)BindHookHandlerShut(pattern string, handler HandlerFunc) error {
for domain, _ := range d.m {
if err := d.s.BindHookHandlerShut(pattern + "@" + domain, handler); err != nil {
return err
}
}
return nil
}

View File

@ -68,10 +68,11 @@ func (s *Server)callHandler(h *HandlerItem, r *Request) {
c := reflect.New(h.ctype)
c.MethodByName("Init").Call([]reflect.Value{reflect.ValueOf(r)})
c.MethodByName(h.fname).Call(nil)
c.MethodByName("Shut").Call(nil)
c.MethodByName("Shut").Call([]reflect.Value{reflect.ValueOf(r)})
} else {
// 直接调用注册的方法处理请求
s.callHookHandlerInit(r)
h.faddr(r)
s.callHookHandlerShut(r)
}
// 路由规则打包
if buffer, err := s.Router.Patch(r.Response.Buffer()); err == nil {
@ -89,6 +90,36 @@ func (s *Server)callHandler(h *HandlerItem, r *Request) {
s.closeQueue.PushBack(r)
}
// 按照Init回调函数的注册顺序进行调用
func (s *Server)callHookHandlerInit(r *Request) {
var l []HandlerFunc
l = s.getInitHookList(gDEFAULT_DOMAIN, r.Method, r.URL.Path)
if l == nil {
l = s.getInitHookList(strings.Split(r.Host, ":")[0], r.Method, r.URL.Path)
}
if l == nil {
return
}
for _, f := range l {
f(r)
}
}
// 按照Shut回调函数的注册顺序进行调用
func (s *Server)callHookHandlerShut(r *Request) {
var l []HandlerFunc
l = s.getShutHookList(gDEFAULT_DOMAIN, r.Method, r.URL.Path)
if l == nil {
l = s.getShutHookList(strings.Split(r.Host, ":")[0], r.Method, r.URL.Path)
}
if l == nil {
return
}
for _, f := range l {
f(r)
}
}
// 处理静态文件请求
func (s *Server)serveFile(w http.ResponseWriter, r *http.Request) {
uri := r.URL.String()

View File

@ -86,7 +86,7 @@ func (r *Router) Dispatch(uri string) (string, error) {
}
for _, rule := range r.dkeys {
if replace := r.drules.Get(rule); replace != "" {
result, err := gregx.ReplaceString(rule, uri, replace)
result, err := gregx.ReplaceString(rule, replace, uri)
if err != nil {
return result, err
}
@ -107,7 +107,7 @@ func (r *Router) Patch(content []byte) ([]byte, error) {
}
for _, rule := range r.pkeys {
if replace := r.prules.Get(rule); replace != "" {
result, err := gregx.Replace(rule, content, []byte(replace))
result, err := gregx.Replace(rule, []byte(replace), content)
if err != nil {
return result, err
}

View File

@ -54,6 +54,6 @@ func Replace(pattern string, replace, src []byte) ([]byte, error) {
// 正则替换(全部替换),字符串
func ReplaceString(pattern, replace, src string) (string, error) {
r, e := Replace(pattern, []byte(src), []byte(replace))
r, e := Replace(pattern, []byte(replace), []byte(src))
return string(r), e
}

View File

@ -0,0 +1,21 @@
package demo
import "gitee.com/johng/gf/g/net/ghttp"
func init() {
ghttp.GetServer().BindHandler("/hook", func(r *ghttp.Request){
r.Response.WriteString("This is hook content!\n")
})
ghttp.GetServer().BindHookHandlerInit("/hook", func(r *ghttp.Request){
r.Response.WriteString("Init hook 1!\n")
})
ghttp.GetServer().BindHookHandlerInit("/hook", func(r *ghttp.Request){
r.Response.WriteString("Init hook 2!\n")
})
ghttp.GetServer().BindHookHandlerShut("/hook", func(r *ghttp.Request){
r.Response.WriteString("Shut hook 1!\n")
})
ghttp.GetServer().BindHookHandlerShut("/hook", func(r *ghttp.Request){
r.Response.WriteString("Shut hook 2!\n")
})
}