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 }