feat: 自动字段注入支持解析二级匿名字段
This commit is contained in:
@ -36,24 +36,42 @@ func (s *server) AddCommonParamRules(rules map[string]GetCommonParam) {
|
|||||||
func (s *server) injectCommonParam(ctx *gin.Context, formValue any) error {
|
func (s *server) injectCommonParam(ctx *gin.Context, formValue any) error {
|
||||||
innerCtx := util.GinCtxToContext(ctx)
|
innerCtx := util.GinCtxToContext(ctx)
|
||||||
var (
|
var (
|
||||||
val any
|
val any
|
||||||
err error
|
err error
|
||||||
|
reflectFormValue reflect.Value
|
||||||
|
reflectType reflect.Type
|
||||||
|
ok bool
|
||||||
)
|
)
|
||||||
|
|
||||||
reflectType := reflect.TypeOf(formValue)
|
if reflectFormValue, ok = formValue.(reflect.Value); !ok {
|
||||||
|
reflectFormValue = reflect.ValueOf(formValue)
|
||||||
|
reflectType = reflect.TypeOf(formValue)
|
||||||
|
} else {
|
||||||
|
reflectType = reflectFormValue.Type()
|
||||||
|
}
|
||||||
|
|
||||||
fieldTable := map[string]bool{}
|
fieldTable := map[string]bool{}
|
||||||
fieldNum := reflectType.Elem().NumField()
|
fieldNum := reflectType.Elem().NumField()
|
||||||
for i := 0; i < fieldNum; i++ {
|
for i := 0; i < fieldNum; i++ {
|
||||||
// 提取全部结构体字段
|
if reflectType.Elem().Field(i).Anonymous && ((reflectType.Elem().Field(i).Type.Kind() == reflect.Ptr && reflectType.Elem().Field(i).Type.Kind() == reflect.Struct) || reflectType.Elem().Field(i).Type.Kind() == reflect.Struct) {
|
||||||
fieldTable[reflectType.Elem().Field(i).Name] = true
|
anonymousFieldType := reflectType.Elem().Field(i).Type
|
||||||
|
if anonymousFieldType.Kind() == reflect.Ptr {
|
||||||
|
anonymousFieldType = anonymousFieldType.Elem()
|
||||||
|
}
|
||||||
|
for j := 0; j < anonymousFieldType.NumField(); j++ {
|
||||||
|
fieldTable[anonymousFieldType.Field(j).Name] = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 提取全部结构体字段
|
||||||
|
fieldTable[reflectType.Elem().Field(i).Name] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
reflectValue := reflect.ValueOf(formValue)
|
|
||||||
for fieldName, getParamFunc := range s.commonParam {
|
for fieldName, getParamFunc := range s.commonParam {
|
||||||
if _, ok := fieldTable[fieldName]; !ok {
|
if _, ok = fieldTable[fieldName]; !ok {
|
||||||
// 结构体字段未配置自动注入
|
// 结构体字段未配置自动注入
|
||||||
logger.Instance.Debug("当前结构体不包含指定字段, 忽略执行", pkgLogger.NewLogData(innerCtx, logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
|
logger.Instance.Debug("当前结构体不包含指定字段, 忽略执行", pkgLogger.NewLogData(innerCtx, logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
|
||||||
"field_name": fieldName,
|
"field_name": fieldName,
|
||||||
"struct": reflectValue.Elem().Type().String(),
|
"struct": reflectFormValue.Elem().Type().String(),
|
||||||
}).ToFieldList()...)
|
}).ToFieldList()...)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -64,7 +82,7 @@ func (s *server) injectCommonParam(ctx *gin.Context, formValue any) error {
|
|||||||
}).ToFieldList()...)
|
}).ToFieldList()...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fieldValue := reflectValue.Elem().FieldByName(fieldName)
|
fieldValue := reflectFormValue.Elem().FieldByName(fieldName)
|
||||||
if !fieldValue.CanSet() {
|
if !fieldValue.CanSet() {
|
||||||
logDataList := pkgLogger.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
|
logDataList := pkgLogger.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
|
||||||
"field_name": fieldName,
|
"field_name": fieldName,
|
||||||
|
|||||||
@ -46,10 +46,11 @@ func (s *server) getFormInitValue(ctx *gin.Context, uriCfg UriConfig) (any, erro
|
|||||||
func (s *server) RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
|
func (s *server) RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
|
||||||
return func(ctx *gin.Context) {
|
return func(ctx *gin.Context) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
ok bool
|
ok bool
|
||||||
e exception.IException
|
e exception.IException
|
||||||
formValue any
|
formValue any
|
||||||
|
firstParam reflect.Value
|
||||||
)
|
)
|
||||||
|
|
||||||
if formValue, err = s.getFormInitValue(ctx, uriCfg); nil != err {
|
if formValue, err = s.getFormInitValue(ctx, uriCfg); nil != err {
|
||||||
@ -60,6 +61,17 @@ func (s *server) RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
|
|||||||
ctx.Abort()
|
ctx.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 表单数据
|
||||||
|
inputValue := reflect.ValueOf(formValue)
|
||||||
|
// 注入公共参数
|
||||||
|
if err = s.injectCommonParam(ctx, inputValue); nil != err {
|
||||||
|
e = exception.NewFromError(500, err)
|
||||||
|
response.SendWithException(ctx, e, &define.ResponseOption{
|
||||||
|
ContentType: consts.MimeTypeJson,
|
||||||
|
})
|
||||||
|
ctx.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
isSuccess := false
|
isSuccess := false
|
||||||
// 初始化响应之后logic
|
// 初始化响应之后logic
|
||||||
@ -94,11 +106,9 @@ func (s *server) RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
|
|||||||
}()
|
}()
|
||||||
}()
|
}()
|
||||||
// 执行逻辑
|
// 执行逻辑
|
||||||
inputValue := reflect.ValueOf(formValue)
|
|
||||||
if uriCfg.FormDataType.Kind() != reflect.Ptr {
|
if uriCfg.FormDataType.Kind() != reflect.Ptr {
|
||||||
inputValue = inputValue.Elem()
|
inputValue = inputValue.Elem()
|
||||||
}
|
}
|
||||||
var firstParam reflect.Value
|
|
||||||
if uriCfg.CtxType == CustomContextType {
|
if uriCfg.CtxType == CustomContextType {
|
||||||
customCtx := ctx.MustGet(define.CustomContextKey)
|
customCtx := ctx.MustGet(define.CustomContextKey)
|
||||||
firstParam = reflect.ValueOf(customCtx)
|
firstParam = reflect.ValueOf(customCtx)
|
||||||
@ -109,7 +119,7 @@ func (s *server) RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
|
|||||||
if resList[1].IsNil() {
|
if resList[1].IsNil() {
|
||||||
// 请求成功
|
// 请求成功
|
||||||
isSuccess = true
|
isSuccess = true
|
||||||
response.SuccessWithExtension(ctx, resList[0].Interface(), &define.ResponseOption{ContentType: "application/json;charset=utf-8"})
|
response.SuccessWithExtension(ctx, resList[0].Interface(), &define.ResponseOption{ContentType: consts.MimeTypeJson})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 请求失败
|
// 请求失败
|
||||||
@ -123,7 +133,7 @@ func (s *server) RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
response.SendWithException(ctx, e, &define.ResponseOption{
|
response.SendWithException(ctx, e, &define.ResponseOption{
|
||||||
ContentType: "application/json;charset=utf-8",
|
ContentType: consts.MimeTypeJson,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -126,11 +126,12 @@ func NewServer(port int, optionList ...SetServerOptionFunc) *server {
|
|||||||
pprof.Register(r)
|
pprof.Register(r)
|
||||||
}
|
}
|
||||||
return &server{
|
return &server{
|
||||||
router: r,
|
router: r,
|
||||||
uiInstance: apiDoc.NewSwaggerUI(option.serverInfo, option.serverList, apiDocEnum.SwaggerUITheme(option.swaggerUiTheme)),
|
uiInstance: apiDoc.NewSwaggerUI(option.serverInfo, option.serverList, apiDocEnum.SwaggerUITheme(option.swaggerUiTheme)),
|
||||||
port: port,
|
port: port,
|
||||||
option: option,
|
option: option,
|
||||||
lock: &sync.RWMutex{},
|
lock: &sync.RWMutex{},
|
||||||
|
commonParam: map[string]GetCommonParam{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,8 +13,28 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type testCommon struct {
|
||||||
|
UserID uint `json:"user_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type testForm struct {
|
||||||
|
Meta `json:"-" method:"get" path:"test"`
|
||||||
|
testCommon
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewServer(t *testing.T) {
|
func TestNewServer(t *testing.T) {
|
||||||
s := NewServer(9087)
|
s := NewServer(9087)
|
||||||
s.Router().GET("/ping", func(c *gin.Context) {})
|
s.AddCommonParamRule("UserID", func(ctx *gin.Context) (any, error) {
|
||||||
|
return uint(123456), nil
|
||||||
|
})
|
||||||
|
s.Group("", nil, testController{})
|
||||||
s.Start()
|
s.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type testController struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tc testController) Test(ctx *gin.Context, requestData *testForm) (*testCommon, error) {
|
||||||
|
return &testCommon{UserID: requestData.UserID}, nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user