diff --git a/define/response.go b/define/response.go index 3ff6e63..5829670 100644 --- a/define/response.go +++ b/define/response.go @@ -10,6 +10,7 @@ package define import ( "git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/wrapper" + "sync" ) var ( @@ -124,3 +125,24 @@ func GetHttpHandleConfig() *HttpHandleConfig { ).Value(), } } + +const ( + LogicAfterResponseKey = "__logic_after_response__" +) + +type LogicAfterResponse struct { + SuccessHookFuncList []func() `json:"-"` // 请求最后需要执行的成功hook函数 + FailureHookFuncList []func() `json:"-"` // 请求最后需要执行的失败hook函数 + Lock *sync.RWMutex `json:"-"` // 逻辑锁 +} + +func (logic *LogicAfterResponse) AddSuccessHook(f func()) { + logic.Lock.Lock() + defer logic.Lock.Unlock() + logic.SuccessHookFuncList = append(logic.SuccessHookFuncList, f) +} +func (logic *LogicAfterResponse) AddFailureHook(f func()) { + logic.Lock.Lock() + defer logic.Lock.Unlock() + logic.FailureHookFuncList = append(logic.FailureHookFuncList, f) +} diff --git a/request/wrapper.go b/request/wrapper.go index 5a14c12..0e1d09d 100644 --- a/request/wrapper.go +++ b/request/wrapper.go @@ -8,10 +8,12 @@ package request import ( + "git.zhangdeman.cn/zhangdeman/gin/define" "git.zhangdeman.cn/zhangdeman/gin/request/parse_body" "git.zhangdeman.cn/zhangdeman/wrapper" "github.com/gin-gonic/gin" "strings" + "sync" ) var ( @@ -302,3 +304,25 @@ func (wh *wrapperHandle) Copy(ctx *gin.Context, isCopyContextValue bool, exclude } return newContext } + +// GetLogicAfterResponse ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 16:54 2025/2/28 +func (wh *wrapperHandle) GetLogicAfterResponse(ctx *gin.Context) *define.LogicAfterResponse { + if nil == ctx || nil == ctx.Request { + return nil + } + l, exist := ctx.Get(define.LogicAfterResponseKey) + if !exist || nil == l { + l = &define.LogicAfterResponse{ + SuccessHookFuncList: make([]func(), 0), + FailureHookFuncList: make([]func(), 0), + Lock: &sync.RWMutex{}, + } + ctx.Set(define.LogicAfterResponseKey, l) + } + // 就这么写, key值如果被其他人覆盖成非法值, 此处会直接panic + return l.(*define.LogicAfterResponse) +} diff --git a/router/define.go b/router/define.go index 605f26e..bc49eb7 100644 --- a/router/define.go +++ b/router/define.go @@ -7,7 +7,9 @@ // Date : 2024-07-20 22:57 package router -import "reflect" +import ( + "reflect" +) const ( PrefixFuncName = "RouterPrefix" // 路由前缀函数名称 diff --git a/router/handler.go b/router/handler.go index 5f85d45..f0a28dc 100644 --- a/router/handler.go +++ b/router/handler.go @@ -9,10 +9,12 @@ package router import ( "git.zhangdeman.cn/zhangdeman/exception" + "git.zhangdeman.cn/zhangdeman/gin/define" "git.zhangdeman.cn/zhangdeman/gin/request" "git.zhangdeman.cn/zhangdeman/gin/response" "github.com/gin-gonic/gin" "reflect" + "sync" ) // RequestHandler 获取请求处理方法 @@ -45,6 +47,33 @@ func RequestHandler(uriCfg UriConfig) gin.HandlerFunc { return } + isSuccess := false + // 初始化响应之后logic + logicAfterResponse := &define.LogicAfterResponse{ + SuccessHookFuncList: make([]func(), 0), + FailureHookFuncList: make([]func(), 0), + Lock: &sync.RWMutex{}, + } + // 此处暴露出去,是为了使用方可以获取到对应数据 + ctx.Set(define.LogicAfterResponseKey, logicAfterResponse) + defer func() { + go func() { + defer recover() + if isSuccess { + for _, itemFunc := range logicAfterResponse.SuccessHookFuncList { + if nil != itemFunc { + itemFunc() + } + } + } else { + for _, itemFunc := range logicAfterResponse.FailureHookFuncList { + if nil != itemFunc { + itemFunc() + } + } + } + }() + }() // 执行逻辑 inputValue := reflect.ValueOf(formValue) if uriCfg.FormDataType.Kind() != reflect.Ptr { @@ -53,22 +82,20 @@ func RequestHandler(uriCfg UriConfig) gin.HandlerFunc { resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, reflect.ValueOf(ctx), inputValue}) if resList[1].IsNil() { // 请求成功 + isSuccess = true response.Success(ctx, resList[0].Interface()) return } // 请求失败 if e, ok = resList[1].Interface().(exception.IException); ok { - response.SendWithException(ctx, e, nil) - return - } - if err, ok = resList[1].Interface().(error); ok { + // 本身就是exception.IException + } else if err, ok = resList[1].Interface().(error); ok { e = exception.NewFromError(-1, err) - response.SendWithException(ctx, e, nil) - return + } else { + e = exception.NewWithCodeAndData(-1, map[string]any{ + "err": resList[1].Interface(), + }) } - e = exception.NewWithCodeAndData(-1, map[string]any{ - "err": resList[1].Interface(), - }) response.SendWithException(ctx, e, nil) return }