event/reflect.go

397 lines
10 KiB
Go
Raw Normal View History

// Package event ...
//
// Description : event ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-02-01 14:30
package event
import (
2023-02-02 14:47:46 +08:00
"encoding/json"
"git.zhangdeman.cn/zhangdeman/event/abstract"
"git.zhangdeman.cn/zhangdeman/util"
2023-02-02 14:47:46 +08:00
"github.com/tidwall/gjson"
"net/http"
"reflect"
"strings"
"sync"
)
var (
// ReflectTypeInstance 反射实例
ReflectTypeInstance *ReflectType
)
func init() {
ReflectTypeInstance = &ReflectType{
lock: &sync.RWMutex{},
cacheTable: make(map[string]*StructInfo),
}
}
// ReflectType 反射数据类型
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:31 2023/2/1
type ReflectType struct {
// 数据锁
lock *sync.RWMutex
// 反射结果缓存
cacheTable map[string]*StructInfo
}
// Do 反射获取数据类型
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:34 2023/2/1
//
// 为特定结构体生成全局唯一的标识, 并进行缓存, 加速反射结果获取
func (rt *ReflectType) Do(dataFlag string, data interface{}) *StructInfo {
rt.lock.Lock()
defer rt.lock.Unlock()
if cacheResult, exist := rt.cacheTable[dataFlag]; exist {
// 缓存存在, 直接是有缓存结果
return cacheResult
}
// 缓存不存在, 解析
res := &StructInfo{
Flag: dataFlag,
IsStruct: false,
IsStructPtr: false,
StructFieldList: make([]*StructField, 0),
}
isPtr := false
reflectType := reflect.TypeOf(data)
if reflectType.Kind() == reflect.Ptr {
isPtr = true
reflectType = reflectType.Elem()
}
if reflectType.Kind() != reflect.Struct {
// 非结构体,无需反射
2023-02-01 20:37:02 +08:00
rt.cacheTable[dataFlag] = res
return res
}
res.IsStruct = true
res.IsStructPtr = isPtr
for idx := 0; idx < reflectType.NumField(); idx++ {
field := &StructField{
2023-02-01 20:30:32 +08:00
Idx: idx,
Name: reflectType.Field(idx).Name,
JsonTag: reflectType.Field(idx).Tag.Get(JsonTag),
EventTag: reflectType.Field(idx).Tag.Get(OutEventTag),
MappingRuleList: make([]MappingRuleItem, 0),
}
rt.fillFieldType(field, reflectType.Field(idx).Type)
2023-02-01 20:30:32 +08:00
rt.fillMappingRule(field, reflectType.Field(idx).Tag.Get(MappingTag))
res.StructFieldList = append(res.StructFieldList, field)
}
2023-02-01 20:35:33 +08:00
rt.cacheTable[dataFlag] = res
return res
}
2023-02-02 10:52:40 +08:00
// fillFieldType 填充字段类型
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:46 2023/2/1
func (rt *ReflectType) fillFieldType(field *StructField, dataType reflect.Type) {
switch dataType.Kind() {
2023-02-02 10:52:40 +08:00
case reflect.Float32:
fallthrough
case reflect.Float64:
field.Type = reflect.Float64
case reflect.String:
field.Type = reflect.String
case reflect.Struct:
field.Type = reflect.Struct
2023-02-02 12:30:25 +08:00
case reflect.Slice:
field.Type = reflect.Slice
case reflect.Map:
field.Type = reflect.Map
case reflect.Ptr:
field.IsPtr = true
// 指针再次判断基础类型
field.Type = dataType.Elem().Kind()
2023-02-02 10:52:40 +08:00
default:
if strings.Contains(dataType.String(), "int") {
field.Type = reflect.Int64
} else {
field.Type = reflect.Interface
}
}
}
// fillTagInfo 填充标签信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:11 2023/2/1
func (rt *ReflectType) fillTagInfo(field *StructField) {
if len(field.JsonTag) == 0 {
field.JsonTag = field.Name
}
// jsonTag 去掉 omitempty
jsonTagValArr := strings.Split(field.JsonTag, ",")
for _, item := range jsonTagValArr {
if len(item) > 0 && item != OmitemptyTag {
field.JsonTag = item
break
}
}
2023-02-01 20:30:32 +08:00
// 没有设置event tag,则和 json tag保持一致
if len(field.EventTag) == 0 {
field.EventTag = field.JsonTag
}
}
// fillMappingRule 解析参数映射规则
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:14 2023/2/1
//
// mapping:"user_id:param#user_id|header#id"
2023-02-01 20:30:32 +08:00
func (rt *ReflectType) fillMappingRule(field *StructField, inputMappingVal string) {
if len(inputMappingVal) == 0 {
// 没有指定规则, 有默认规则
for _, location := range mappingLocationList {
2023-02-01 20:30:32 +08:00
field.MappingRuleList = append(field.MappingRuleList, MappingRuleItem{
Location: location,
Field: field.JsonTag,
})
}
return
}
mappingArr := strings.Split(inputMappingVal, ",")
for _, item := range mappingArr {
item = strings.TrimSpace(item)
// 要赋值的字段名
itemArr := strings.Split(item, ":")
2023-02-01 20:15:15 +08:00
if len(itemArr) != 2 {
// 配置格式错误, 跳过
continue
}
mapRuleArr := strings.Split(strings.TrimSpace(itemArr[1]), "|")
for _, itemMapRule := range mapRuleArr {
itemMapRule = strings.TrimLeft(itemMapRule, "#")
itemMapRuleArr := strings.Split(itemMapRule, "#")
// 注意 : # 为特殊分隔符, 如配置成 mapping:"project_id:#source_project_id#xxx_project_id" 实际等价于 mapping:"project_id:#source_project_id" 多余配置自动跳过
if len(itemMapRuleArr[0]) < 2 {
// 没有指定位置默认all, 即配置格式: mapping:"project_id:#source_project_id"
itemMapRuleArr[0] = MappingLocationAll
itemMapRuleArr = []string{MappingLocationAll, itemMapRuleArr[0]}
}
switch itemMapRuleArr[0] {
// 从header读取
case MappingLocationHeader:
2023-02-01 20:30:32 +08:00
field.MappingRuleList = append(field.MappingRuleList, MappingRuleItem{
2023-02-01 20:15:15 +08:00
Location: MappingLocationHeader,
Field: itemMapRuleArr[1],
})
// 从请求参数读取
case MappingLocationParam:
2023-02-01 20:30:32 +08:00
field.MappingRuleList = append(field.MappingRuleList, MappingRuleItem{
2023-02-01 20:15:15 +08:00
Location: MappingLocationParam,
Field: itemMapRuleArr[1],
})
// 从响应数据读取
case MappingLocationResponse:
2023-02-01 20:30:32 +08:00
field.MappingRuleList = append(field.MappingRuleList, MappingRuleItem{
2023-02-01 20:15:15 +08:00
Location: MappingLocationResponse,
Field: itemMapRuleArr[1],
})
// 从扩展数据读取
case MappingLocationExtension:
2023-02-01 20:30:32 +08:00
field.MappingRuleList = append(field.MappingRuleList, MappingRuleItem{
2023-02-01 20:15:15 +08:00
Location: MappingLocationExtension,
Field: itemMapRuleArr[1],
})
// 全部读取一遍
case MappingLocationAll:
fallthrough
default:
for _, itemLocation := range mappingLocationList {
2023-02-01 20:30:32 +08:00
field.MappingRuleList = append(field.MappingRuleList, MappingRuleItem{
2023-02-01 20:15:15 +08:00
Location: itemLocation,
Field: itemMapRuleArr[1],
})
}
}
}
}
}
// ReflectValue 反射值的实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:53 2023/2/2
type ReflectValue struct {
}
// Do 通过反射机制对data进行数据填充此逻辑要求 data 必须是结构体或者结构体指针
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:52 2023/2/2
func (rv *ReflectValue) Do(dataFlag string, data interface{}, preSendHandler abstract.IPreSendHandler) {
structInfo := ReflectTypeInstance.Do(dataFlag, data)
if !structInfo.IsStruct {
return
}
reflectValue := reflect.ValueOf(data)
if structInfo.IsStructPtr {
reflectValue = reflectValue.Elem()
}
for _, fieldInfo := range structInfo.StructFieldList {
if !rv.isZeroInputFieldValue(reflectValue, fieldInfo) {
// 不是零值, 无需处理
continue
}
// 是零值, 填充默认值
}
}
// isZeroInputFieldValue 判断对应的字段是否为对应类型默认的零值
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:04 2023/2/2
func (rv *ReflectValue) isZeroInputFieldValue(reflectValue reflect.Value, fieldInfo *StructField) bool {
inputVal := reflectValue.Field(fieldInfo.Idx).Interface()
switch fieldInfo.Type {
case reflect.Float64:
var f float64
if err := util.ConvertAssign(&f, inputVal); nil == err {
if f != 0 {
return false
}
return true
}
case reflect.String:
var s string
if err := util.ConvertAssign(&s, inputVal); nil == err {
if len(s) > 0 {
return false
}
return true
}
case reflect.Int64:
var i int64
if err := util.ConvertAssign(&i, inputVal); nil == err {
if i != 0 {
return false
}
return true
}
2023-02-02 12:30:25 +08:00
case reflect.Map:
if nil == inputVal {
return true
}
var m map[interface{}]interface{}
if err := util.ConvertAssign(&m, inputVal); nil == err {
if len(m) != 0 {
return false
}
return true
}
case reflect.Slice:
if nil == inputVal {
return true
}
var sl []interface{}
if err := util.ConvertAssign(&sl, inputVal); nil == err {
if len(sl) != 0 {
return false
}
return true
}
case reflect.Interface:
if inputVal == nil {
return true
}
return false
default:
// 默认不处理
return false
}
return false
}
2023-02-02 14:47:46 +08:00
// fillFieldValue 填充字段值
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:00 2023/2/2
func (rv *ReflectValue) fillFieldValue(reflectValue reflect.Value, fieldInfo *StructField, preSendHandler abstract.IPreSendHandler) {
paramByte, _ := json.Marshal(preSendHandler.GetRequestParam())
header := preSendHandler.GetRequestHeader()
responseByte, _ := json.Marshal(preSendHandler.GetResponseData())
extensionByte, _ := json.Marshal(preSendHandler.GetExtensionData())
for _, item := range fieldInfo.MappingRuleList {
}
}
// getInputValue 获取输入的值
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:24 2023/2/2
func (rv *ReflectValue) setDataValue(reflectVal reflect.Value, fieldInfo *StructField, rule MappingRuleItem, header http.Header, paramByte, responseByte, extensionByte []byte) bool {
switch rule.Location {
case MappingLocationHeader:
str := header.Get(rule.Field)
if len(str) == 0 {
// 未进行值设置
return false
}
case MappingLocationParam:
case MappingLocationResponse:
case MappingLocationExtension:
default:
return false
}
return true
}
// getInputValue 获取输入的值
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:43 2023/2/2
func (rv *ReflectValue) getInputValue(rule MappingRuleItem, header http.Header, paramByte, responseByte, extensionByte []byte) string {
switch rule.Location {
case MappingLocationHeader:
return header.Get(rule.Field)
case MappingLocationParam:
return gjson.GetBytes(paramByte, rule.Field).String()
case MappingLocationResponse:
return gjson.GetBytes(responseByte, rule.Field).String()
case MappingLocationExtension:
return gjson.GetBytes(extensionByte, rule.Field).String()
case MappingLocationAll:
str := header.Get(rule.Field)
if len(str) == 0 {
str = gjson.GetBytes(paramByte, rule.Field).String()
}
if len(str) == 0 {
str = gjson.GetBytes(responseByte, rule.Field).String()
}
if len(str) == 0 {
str = gjson.GetBytes(extensionByte, rule.Field).String()
}
return str
default:
return ""
}
}