完成基础反射调用接口 + 数据响应

This commit is contained in:
白茶清欢 2025-02-07 16:57:15 +08:00
parent 77ea723e86
commit e95061a1a8
6 changed files with 44 additions and 46 deletions

View File

@ -8,6 +8,7 @@
package router package router
import ( import (
"fmt"
"reflect" "reflect"
"strings" "strings"
) )
@ -38,25 +39,26 @@ func (c controller) Parse(inputController any) map[string]UriConfig {
} }
controllerType := reflect.TypeOf(inputController) controllerType := reflect.TypeOf(inputController)
controllerValue := reflect.ValueOf(inputController) controllerValue := reflect.ValueOf(inputController)
if controllerType.Kind() == reflect.Func { /*if controllerType.Kind() == reflect.Func {
// 直接函数注册 // 直接函数注册
cfg, isNeedRegister := c.methodConfig(controllerType) cfg, isNeedRegister := c.methodConfig(controllerType)
if isNeedRegister { if isNeedRegister {
parseRes[cfg.Path] = cfg parseRes[cfg.Path] = cfg
} }
return parseRes return parseRes
} }*/
if controllerType.Kind() == reflect.Ptr { if controllerType.Kind() == reflect.Ptr {
controllerValue = controllerValue.Elem() controllerValue = controllerValue.Elem()
} }
if controllerValue.IsNil() { /*if controllerValue.IsNil() {
return parseRes return parseRes
} }*/
for methodIdx := 0; methodIdx < controllerType.NumMethod(); methodIdx++ { for methodIdx := 0; methodIdx < controllerType.NumMethod(); methodIdx++ {
uriCfg, needRegister := c.methodConfig(controllerType.Method(methodIdx).Type) uriCfg, needRegister := c.methodConfig(controllerType.Method(methodIdx))
if !needRegister { if !needRegister {
continue continue
} }
uriCfg.ApiStructValue = controllerValue
parseRes[uriCfg.Path] = uriCfg parseRes[uriCfg.Path] = uriCfg
} }
return parseRes return parseRes
@ -71,7 +73,8 @@ func (c controller) Parse(inputController any) map[string]UriConfig {
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 16:05 2025/1/27 // Date : 16:05 2025/1/27
func (c controller) methodConfig(methodType reflect.Type) (cfg UriConfig, needRegister bool) { func (c controller) methodConfig(reflectMethod reflect.Method) (cfg UriConfig, needRegister bool) {
methodType := reflectMethod.Type
// num0: 函数声明 // num0: 函数声明
// num1: 第一个参数 // num1: 第一个参数
// num2: 第二个参数 // num2: 第二个参数
@ -89,6 +92,7 @@ func (c controller) methodConfig(methodType reflect.Type) (cfg UriConfig, needRe
if formType.Kind() == reflect.Ptr { if formType.Kind() == reflect.Ptr {
formType = methodType.In(2).Elem() formType = methodType.In(2).Elem()
} }
cfg.FormDataType = formType
metaField, metaFieldExist := formType.FieldByName(FieldNameMeta) metaField, metaFieldExist := formType.FieldByName(FieldNameMeta)
if !metaFieldExist { if !metaFieldExist {
needRegister = false needRegister = false
@ -96,34 +100,37 @@ func (c controller) methodConfig(methodType reflect.Type) (cfg UriConfig, needRe
} }
// 解析第一个返回值, 要求必须是结构体或者是map // 解析第一个返回值, 要求必须是结构体或者是map
if methodType.Out(0).Kind() != reflect.Struct && methodType.Out(0).Kind() != reflect.Map { /*if methodType.Out(0).Kind() != reflect.Struct && methodType.Out(0).Kind() != reflect.Map {
needRegister = false needRegister = false
return return
} }*/
if methodType.Out(1).Kind().String() != "error" { if methodType.Out(1).Kind().String() != "error" {
// 判断是否是实现 error接口的方法 // 判断是否是实现 error接口的方法
outputErrParse := false outputErrParse := false
for j := 0; j < methodType.Out(1).NumMethod(); j++ { for j := 0; j < methodType.Out(1).NumMethod(); j++ {
if methodType.Out(1).Method(j).Name == "Error" && // 实现Error方法 if methodType.Out(1).Method(j).Name == "Error" && // 实现Error方法
methodType.Out(1).Method(j).Type.NumIn() == 1 && // 没有任何参数 methodType.Out(1).Method(j).Type.NumIn() == 0 && // 没有任何参数
methodType.Out(1).Method(j).Type.NumOut() == 1 && // 一个返回值 methodType.Out(1).Method(j).Type.NumOut() == 1 && // 一个返回值
methodType.Out(1).Method(j).Type.Out(0).Kind().String() == reflect.String.String() { methodType.Out(1).Method(j).Type.Out(0).Kind().String() == reflect.String.String() {
outputErrParse = true outputErrParse = true
break break
} }
fmt.Println(methodType.Out(1).Method(j).Name, methodType.Out(1).Method(j).Type.NumIn(), methodType.Out(1).Method(j).Type.NumOut(), methodType.Out(1).Method(j).Type.Out(0).Kind().String())
} }
if !outputErrParse { if !outputErrParse {
needRegister = false needRegister = false
}
return return
} }
}
// 解析meta信息 // 解析meta信息
cfg.Path = metaField.Tag.Get(TagNamePath) cfg.Path = metaField.Tag.Get(TagNamePath)
cfg.Method = metaField.Tag.Get(TagNameMethod) cfg.RequestMethod = metaField.Tag.Get(TagNameMethod)
cfg.Desc = metaField.Tag.Get(TagNameDesc) cfg.Desc = metaField.Tag.Get(TagNameDesc)
cfg.TagList = strings.Split(metaField.Tag.Get(TagNameUriTag), ",") cfg.TagList = strings.Split(metaField.Tag.Get(TagNameUriTag), ",")
// 解析参数配置 // 解析参数配置
cfg.ParamList = c.parseParamConfig(formType) cfg.ParamList = c.parseParamConfig(formType)
cfg.ApiLogicFunc = reflectMethod
needRegister = true
return return
} }

View File

@ -32,12 +32,13 @@ const (
// Date : 15:41 2024/7/21 // Date : 15:41 2024/7/21
type UriConfig struct { type UriConfig struct {
Path string `json:"path"` // 接口路由, 必须配置 Path string `json:"path"` // 接口路由, 必须配置
Method string `json:"method"` // 接口请求方法, 必须配置 RequestMethod string `json:"request_method"` // 接口请求方法, 必须配置
TagList []string `json:"tag_list"` // 接口分组 TagList []string `json:"tag_list"` // 接口分组
Desc string `json:"desc"` // 接口描述 Desc string `json:"desc"` // 接口描述
Strict bool `json:"strict"` // 接口是否为严格模式 : 不配置, 则为严格模式.严格模式 : POST 仅解析 BODY , GET 仅解析 QUERY Strict bool `json:"strict"` // 接口是否为严格模式 : 不配置, 则为严格模式.严格模式 : POST 仅解析 BODY , GET 仅解析 QUERY
ParamList []UriParam `json:"param_list"` // 参数信息表 ParamList []UriParam `json:"param_list"` // 参数信息表
FormDataType reflect.Type `json:"-"` // 表单数据类型 FormDataType reflect.Type `json:"-"` // 表单数据类型
ApiStructValue reflect.Value `json:"-"` // 逻辑函数所属结构体取值
ApiLogicFunc reflect.Method `json:"-"` // 自定义的接口逻辑 ApiLogicFunc reflect.Method `json:"-"` // 自定义的接口逻辑
} }

View File

@ -26,7 +26,7 @@ func Group(router *gin.Engine, routerPrefix string, middlewareList []gin.Handler
for _, c := range cList { for _, c := range cList {
urlTable := cParser.Parse(c) urlTable := cParser.Parse(c)
for _, itemUriCfg := range urlTable { for _, itemUriCfg := range urlTable {
method := strings.ToUpper(itemUriCfg.Method) method := strings.ToUpper(itemUriCfg.RequestMethod)
switch method { switch method {
case http.MethodGet: case http.MethodGet:
g.GET(itemUriCfg.Path, RequestHandler(itemUriCfg)) g.GET(itemUriCfg.Path, RequestHandler(itemUriCfg))

View File

@ -31,10 +31,12 @@ func RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
formData := reflect.New(uriCfg.FormDataType).Interface() formData := reflect.New(uriCfg.FormDataType).Interface()
// 表单解析 // 表单解析
if err = request.Form.Parse(ctx, formData); nil != err { if err = request.Form.Parse(ctx, formData); nil != err {
e = exception.NewFromError(400, err)
response.SendWithException(ctx, e, nil)
return return
} }
// 执行逻辑 // 执行逻辑
resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{reflect.ValueOf(ctx), reflect.ValueOf(formData)}) resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, reflect.ValueOf(ctx), reflect.ValueOf(formData)})
if resList[1].IsNil() { if resList[1].IsNil() {
// 请求成功 // 请求成功
response.Success(ctx, resList[0].Interface()) response.Success(ctx, resList[0].Interface())

View File

@ -124,7 +124,7 @@ func parseUriConfig(methodType reflect.Type, routerPrefix string) (*UriConfig, e
} }
uriConfig := &UriConfig{ uriConfig := &UriConfig{
Path: strings.TrimRight(routerPrefix, "/") + "/" + strings.TrimLeft(metaField.Tag.Get(TagNamePath), "/"), Path: strings.TrimRight(routerPrefix, "/") + "/" + strings.TrimLeft(metaField.Tag.Get(TagNamePath), "/"),
Method: strings.ToUpper(metaField.Tag.Get(TagNameMethod)), RequestMethod: strings.ToUpper(metaField.Tag.Get(TagNameMethod)),
TagList: strings.Split(metaField.Tag.Get(TagNameUriTag), "|"), TagList: strings.Split(metaField.Tag.Get(TagNameUriTag), "|"),
Desc: metaField.Tag.Get(TagNameDesc), Desc: metaField.Tag.Get(TagNameDesc),
Strict: wrapper.ArrayType([]string{"", "true"}).Has(strings.ToLower(metaField.Tag.Get(TagNameStrict))) >= 0, Strict: wrapper.ArrayType([]string{"", "true"}).Has(strings.ToLower(metaField.Tag.Get(TagNameStrict))) >= 0,
@ -174,7 +174,7 @@ func registerUri(uriConfig *UriConfig, methodValue reflect.Value, middlewareList
middlewareList = append([]gin.HandlerFunc{ middlewareList = append([]gin.HandlerFunc{
middleware.InitRequest(), middleware.InitRequest(),
}, middlewareList...) }, middlewareList...)
switch uriConfig.Method { switch uriConfig.RequestMethod {
case http.MethodGet: case http.MethodGet:
ginRouter.GET(uriConfig.Path, middlewareList...) ginRouter.GET(uriConfig.Path, middlewareList...)
case http.MethodHead: case http.MethodHead:
@ -196,7 +196,7 @@ func registerUri(uriConfig *UriConfig, methodValue reflect.Value, middlewareList
case "ANY": case "ANY":
ginRouter.Any(uriConfig.Path, middlewareList...) ginRouter.Any(uriConfig.Path, middlewareList...)
default: default:
panic(uriConfig.Path + " : " + uriConfig.Method + " is not support") panic(uriConfig.Path + " : " + uriConfig.RequestMethod + " is not support")
} }
} }

View File

@ -15,24 +15,13 @@ import (
type TestController struct{} type TestController struct{}
func (t *TestController) RouterPrefix() string { func (t TestController) Logic(ctx *gin.Context, formData *TestForm) (any, error) {
return "/uri/prefix"
}
func (t *TestController) RouterMiddleware() []gin.HandlerFunc {
return []gin.HandlerFunc{
func(ctx *gin.Context) {
},
}
}
func (t *TestController) Uri(ctx *gin.Context, formData *TestForm) (any, error) {
return formData, nil return formData, nil
} }
type TestForm struct { type TestForm struct {
Meta `tag:"测试表单" path:"/a/b/c/d" desc:"测试接口" method:"get" strict:"true"` Meta `tag:"测试表单" path:"/a/b/c/d" desc:"测试接口" method:"get" strict:"true"`
Age int `json:"age" form:"age"` Age int `json:"age" form:"age" binding:"min=20"`
Name string `json:"name" form:"name"` Name string `json:"name" form:"name"`
Test *Test `json:"test" form:"test"` Test *Test `json:"test" form:"test"`
Num *int64 `json:"num" form:"num"` Num *int64 `json:"num" form:"num"`
@ -42,8 +31,7 @@ type Test struct {
} }
func Test_parseController(t *testing.T) { func Test_parseController(t *testing.T) {
type args struct { r := gin.Default()
controller any Group(r, "test", nil, TestController{})
} r.Run(":8080")
Register(8080, &TestController{})
} }