goProject/trunk/center/common/httpServer/reflect.go

401 lines
13 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package httpServer
import (
config "common/configsYaml"
"common/resultstatus"
"common/webServer"
"goutil/logUtilPlus"
"reflect"
"strconv"
"strings"
)
const (
// 供客户端访问的模块的后缀
con_ModuleSuffix = "Module"
// 定义用于分隔模块名称和方法名称的分隔符
con_DelimeterOfObjAndMethod = "_"
)
var (
// 定义存放所有方法映射的变量
methodMap = make(map[string]*methodAndInOutTypes)
// 函数返回值类型
responseType reflect.Type = reflect.TypeOf(new(webServer.ResponseObject))
)
// getStructName
// @description: 获取结构体类型的名称
// parameter:
// @structType: 结构体类型
// return:
// @string: 结构体类型的名称
func getStructName(structType reflect.Type) string {
reflectTypeStr := structType.String()
reflectTypeArr := strings.Split(reflectTypeStr, ".")
return reflectTypeArr[len(reflectTypeArr)-1]
}
// getFullModuleName
// @description: 获取完整的模块名称
// parameter:
// @moduleName: 模块名称
// return:
// @string: 完整的模块名称
func getFullModuleName(moduleName string) string {
return moduleName + con_ModuleSuffix
}
// getFullMethodName
// @description: 获取完整的方法名称
// parameter:
// @structName: 结构体名称
// @methodName: 方法名称
// return:
// @string: 完整的方法名称
func getFullMethodName(structName, methodName string) string {
return structName + con_DelimeterOfObjAndMethod + methodName
}
// resolveMethodInOutParams
// @description: 解析方法的输入输出参数
// parameter:
// @method: 方法对应的反射值
// return:
// @inTypes: 输入参数类型集合
// @outTypes: 输出参数类型集合
func resolveMethodInOutParams(method reflect.Value) (inTypes []reflect.Type, outTypes []reflect.Type) {
methodType := method.Type()
for i := 0; i < methodType.NumIn(); i++ {
inTypes = append(inTypes, methodType.In(i))
}
for i := 0; i < methodType.NumOut(); i++ {
outTypes = append(outTypes, methodType.Out(i))
}
return
}
// RegisterFunction
// @description: 将需要对客户端提供方法的对象进行注册
// parameter:
// @structObject: 对象
// return:
func RegisterFunction(structObject interface{}) {
// 获取structObject对应的反射 Type 和 Value
reflectValue := reflect.ValueOf(structObject)
reflectType := reflect.TypeOf(structObject)
// 提取对象类型名称
structName := getStructName(reflectType)
// 获取structObject中返回值为responseObject的方法
for i := 0; i < reflectType.NumMethod(); i++ {
// 获得方法名称
methodName := reflectType.Method(i).Name
// 获得方法及其输入参数的类型列表
method := reflectValue.MethodByName(methodName)
inTypes, outTypes := resolveMethodInOutParams(method)
// 判断输出参数数量是否正确
if len(outTypes) != 1 {
continue
}
// 判断返回值是否为responseObject
if outTypes[0] != responseType {
continue
}
// 添加到列表中
methodMap[getFullMethodName(structName, methodName)] = newmethodAndInOutTypes(method, inTypes, outTypes)
}
}
// CallFunction
// @description: 调用方法
// parameter:
// @requestObj: 客户端对象
// return:
// @responseObj: 请求对象
func CallFunction(requestObj *webServer.RequestObject) (responseObj *webServer.ResponseObject) {
responseObj = webServer.GetInitResponseObj()
var methodAndInOutTypes *methodAndInOutTypes
var ok bool
// 根据传入的ModuleName和MethodName找到对应的方法对象
key := getFullMethodName(requestObj.ModuleName, requestObj.MethodName)
if methodAndInOutTypes, ok = methodMap[key]; !ok {
logUtilPlus.ErrorLog("找不到指定的方法:%s", key)
responseObj.SetResultStatus(resultStatus.NotSpecificMethod)
return
}
// 判断参数数量是否相同
inTypesLength := len(methodAndInOutTypes.InTypes)
paramLength := len(requestObj.Parameters)
if paramLength != inTypesLength {
logUtilPlus.ErrorLog("传入的参数数量不符,本地方法%s的参数数量%d传入的参数数量为%d", key, inTypesLength, paramLength)
responseObj.SetResultStatus(resultStatus.ParamNotMatch)
return
}
// 构造参数
in := make([]reflect.Value, inTypesLength)
for i := 0; i < inTypesLength; i++ {
inTypeItem := methodAndInOutTypes.InTypes[i]
paramItem := requestObj.Parameters[i]
// 已支持类型Client,Player(非基本类型)
// 已支持类型Bool,Int,Int8,Int16,Int32,Int64,Uint,Uint8,Uint16,Uint32,Uint64,Float32,Float64,String
// 已支持类型以及上面所列出类型的Slice类型
// 未支持类型Uintptr,Complex64,Complex128,Array,Chan,Func,Interface,Map,Ptr,Struct,UnsafePointer
// 由于byte与int8同义rune与int32同义所以并不需要单独处理
// 枚举参数的类型,并进行类型转换
switch inTypeItem.Kind() {
case reflect.Bool:
if param_bool, ok := paramItem.(bool); ok {
in[i] = reflect.ValueOf(param_bool)
}
case reflect.Int:
if param_float64, ok := paramItem.(int); ok {
in[i] = reflect.ValueOf(int(param_float64))
}
case reflect.Int8:
if param_float64, ok := paramItem.(float64); ok {
in[i] = reflect.ValueOf(int8(param_float64))
}
case reflect.Int16:
if param_float64, ok := paramItem.(float64); ok {
in[i] = reflect.ValueOf(int16(param_float64))
}
case reflect.Int32:
if param_float64, ok := paramItem.(float64); ok {
in[i] = reflect.ValueOf(int32(param_float64))
}
case reflect.Int64:
if param_float64, ok := paramItem.(int64); ok {
in[i] = reflect.ValueOf(int64(param_float64))
} else if param_uint64, ok := paramItem.(uint64); ok {
in[i] = reflect.ValueOf(int64(param_uint64))
} else if param_string, ok := paramItem.(string); ok {
i64, err := strconv.ParseInt(param_string, 10, 64)
if err == nil {
in[i] = reflect.ValueOf(i64)
}
}
case reflect.Uint:
if param_float64, ok := paramItem.(float64); ok {
in[i] = reflect.ValueOf(uint(param_float64))
}
case reflect.Uint8:
if param_float64, ok := paramItem.(uint8); ok {
in[i] = reflect.ValueOf(uint8(param_float64))
}
case reflect.Uint16:
if param_float64, ok := paramItem.(uint16); ok {
in[i] = reflect.ValueOf(uint16(param_float64))
}
case reflect.Uint32:
if param_float64, ok := paramItem.(float64); ok {
in[i] = reflect.ValueOf(uint32(param_float64))
}
case reflect.Uint64:
if param_float64, ok := paramItem.(float64); ok {
in[i] = reflect.ValueOf(uint64(param_float64))
}
case reflect.Float32:
if param_float64, ok := paramItem.(float64); ok {
in[i] = reflect.ValueOf(float32(param_float64))
}
case reflect.Float64:
if param_float64, ok := paramItem.(float64); ok {
in[i] = reflect.ValueOf(param_float64)
}
case reflect.String:
if param_string, ok := paramItem.(string); ok {
in[i] = reflect.ValueOf(param_string)
}
case reflect.Slice:
// 如果是Slice类型则需要对其中的项再次进行类型判断及类型转换
if param_interface, ok := paramItem.([]interface{}); ok {
switch inTypeItem.String() {
case "[]bool":
params_inner := make([]bool, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
if param_bool, ok := param_interface[i].(bool); ok {
params_inner[i] = param_bool
}
}
in[i] = reflect.ValueOf(params_inner)
case "[]int":
params_inner := make([]int, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
if param_float64, ok := param_interface[i].(int); ok {
params_inner[i] = int(param_float64)
}
}
in[i] = reflect.ValueOf(params_inner)
case "[]int8":
params_inner := make([]int8, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
if param_float64, ok := param_interface[i].(float64); ok {
params_inner[i] = int8(param_float64)
}
}
in[i] = reflect.ValueOf(params_inner)
case "[]int16":
params_inner := make([]int16, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
if param_float64, ok := param_interface[i].(float64); ok {
params_inner[i] = int16(param_float64)
}
}
in[i] = reflect.ValueOf(params_inner)
case "[]int32":
params_inner := make([]int32, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
param_float64, ok := param_interface[i].(int32)
if ok {
params_inner[i] = int32(param_float64)
continue
} else {
param_int16, right := param_interface[i].(uint16)
if right == true {
params_inner[i] = int32(param_int16)
}
}
}
in[i] = reflect.ValueOf(params_inner)
case "[]int64":
params_inner := make([]int64, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
if param_float64, ok := param_interface[i].(int64); ok {
params_inner[i] = int64(param_float64)
} else if param_uint64, ok := param_interface[i].(uint64); ok {
params_inner[i] = int64(param_uint64)
} else if param_string, ok := param_interface[i].(string); ok {
i64, err := strconv.ParseInt(param_string, 10, 64)
if err == nil {
params_inner[i] = i64
}
}
}
in[i] = reflect.ValueOf(params_inner)
case "[]uint":
params_inner := make([]uint, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
if param_float64, ok := param_interface[i].(uint); ok {
params_inner[i] = uint(param_float64)
}
}
in[i] = reflect.ValueOf(params_inner)
// case "[]uint8": 特殊处理
case "[]uint16":
params_inner := make([]uint16, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
if param_float64, ok := param_interface[i].(uint16); ok {
params_inner[i] = uint16(param_float64)
}
}
in[i] = reflect.ValueOf(params_inner)
case "[]uint32":
params_inner := make([]uint32, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
if param_float64, ok := param_interface[i].(uint32); ok {
params_inner[i] = uint32(param_float64)
}
}
in[i] = reflect.ValueOf(params_inner)
case "[]uint64":
params_inner := make([]uint64, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
if param_float64, ok := param_interface[i].(uint64); ok {
params_inner[i] = uint64(param_float64)
}
}
in[i] = reflect.ValueOf(params_inner)
case "[]float32":
params_inner := make([]float32, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
if param_float64, ok := param_interface[i].(float64); ok {
params_inner[i] = float32(param_float64)
}
}
in[i] = reflect.ValueOf(params_inner)
case "[]float64":
params_inner := make([]float64, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
if param_float64, ok := param_interface[i].(float64); ok {
params_inner[i] = param_float64
}
}
in[i] = reflect.ValueOf(params_inner)
case "[]string":
params_inner := make([]string, len(param_interface), len(param_interface))
for i := 0; i < len(param_interface); i++ {
if param_string, ok := param_interface[i].(string); ok {
params_inner[i] = param_string
}
}
in[i] = reflect.ValueOf(params_inner)
}
} else if inTypeItem.String() == "[]uint8" { // 由于[]uint8在传输过程中会被转化成字符串所以单独处理;
if param_string, ok := paramItem.(string); ok {
param_uint8 := ([]uint8)(param_string)
in[i] = reflect.ValueOf(param_uint8)
}
}
}
}
// 判断是否有无效的参数(传入的参数类型和方法定义的类型不匹配导致没有赋值)
for _, item := range in {
if reflect.Value.IsValid(item) == false {
logUtilPlus.ErrorLog("type:%v,value:%v.方法%s传入的参数%v无效", reflect.TypeOf(item), reflect.ValueOf(item), key, requestObj.Parameters)
responseObj.SetResultStatus(resultStatus.ParamInValid)
return
}
}
// 传入参数,调用方法
if config.DEBUG {
if requestObj.MethodName != "GetRefreshData" {
logUtilPlus.DebugLog("Begin Call Func:module:%v, method:%v,inParams:%v\n\n", requestObj.ModuleName, requestObj.MethodName, in)
}
}
out := methodAndInOutTypes.Method.Call(in)
if config.DEBUG {
if requestObj.MethodName != "GetRefreshData" {
for i, v := range in {
logUtilPlus.DebugLog("\nparams %v,%v\n", i, v)
}
}
}
// 并输出结果到客户端由于只有一个返回值所以取out[0]
if responseObj, ok = (&out[0]).Interface().(*webServer.ResponseObject); !ok {
logUtilPlus.ErrorLog("返回值类型推断为ResponseObject 出错, tyep is :%v", reflect.TypeOf(out[0]))
responseObj.SetResultStatus(resultStatus.ParamInValid)
return
}
if config.DEBUG {
if requestObj.MethodName != "GetRefreshData" {
logUtilPlus.DebugLog("返回数据:code:%v, data:%v, mess:%v\n\n", responseObj.Code, responseObj.Value, responseObj.Message)
}
}
return
}