You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
3.7 KiB
163 lines
3.7 KiB
package middleware |
|
|
|
import ( |
|
"fmt" |
|
"reflect" |
|
"sort" |
|
"strconv" |
|
"strings" |
|
|
|
"go-common/library/log" |
|
) |
|
|
|
const ( |
|
//TypeMiddleAll 全部操作都允许 |
|
TypeMiddleAll = int8(0) |
|
//TypeMiddleEncode 只允许编码,后端返回给前端的响应处理 |
|
TypeMiddleEncode = int8(1) |
|
//TypeMiddleDecode 只允许解码,前端请求后端的请求参数处理 |
|
TypeMiddleDecode = int8(2) |
|
) |
|
|
|
//Aggregate 前端映射结构,对应于前后端交互的字段 |
|
type Aggregate struct { |
|
Hitn string `json:"hitn"` //name的多个结构体用.表示分级 |
|
Hitv string `json:"hitv"` //枚举值 |
|
Mapn string `json:"mapn"` //映射字段名,可以与hitname不同,也可以相同 |
|
Mapv string `json:"mapv"` //映射字段值 |
|
Delimiter string `json:"delimiter"` //映射字段值的分隔符号 |
|
Order int64 `json:"order"` //顺序 |
|
Type int8 `json:"type"` |
|
} |
|
|
|
func (f *Aggregate) Process(data interface{}, encode bool) { |
|
var ( |
|
field, fieldm reflect.Value |
|
fieldExist, hited bool |
|
) |
|
|
|
defer func() { |
|
if errs := recover(); errs != nil { |
|
log.Error("Aggregate Process error(%+v)", errs) |
|
} |
|
}() |
|
hitn := f.Hitn |
|
hitv := strings.Split(f.Hitv, f.Delimiter) |
|
mapn := f.Mapn |
|
mapv := f.Mapv |
|
if !encode { |
|
hitn = f.Mapn |
|
hitv = strings.Split(f.Mapv, f.Delimiter) |
|
mapn = f.Hitn |
|
mapv = f.Hitv |
|
} |
|
|
|
//check fields exist |
|
fv := reflect.ValueOf(data) |
|
if field, fieldExist = getFieldByName(fv, hitn); !fieldExist { |
|
log.Warn("no field for hit(%s) data(%+v)", hitn, data) |
|
return |
|
} |
|
if mapn == hitn { |
|
fieldm = field |
|
} else if fieldm, fieldExist = getFieldByName(fv, mapn); !fieldExist || !fieldm.CanSet() { |
|
log.Warn("no field for map(%s) data(%+v)", mapn, data) |
|
return |
|
} |
|
|
|
fieldv := fmt.Sprintf("%v", field.Interface()) |
|
for _, hit := range hitv { |
|
if fieldv == hit { |
|
hited = true |
|
break |
|
} |
|
} |
|
if !hited { |
|
return |
|
} |
|
|
|
log.Info("got hit field(%s) value(%s) config(%+v)", hitn, fieldv, f) |
|
switch fieldm.Kind() { |
|
case reflect.String: |
|
fieldm.SetString(mapv) |
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |
|
vv, err := strconv.ParseInt(mapv, 10, 64) |
|
if err != nil { |
|
log.Error("strconv.ParseInt(%s) error(%v)", mapv, err) |
|
return |
|
} |
|
fieldm.SetInt(vv) |
|
default: |
|
log.Warn("not support field.kind(%s) for field(%s)", fieldm.Kind().String(), mapn) |
|
} |
|
} |
|
|
|
//getFieldByName 迭代遍历struct,获取指定名字的字段 |
|
func getFieldByName(v reflect.Value, name string) (res reflect.Value, ok bool) { |
|
tp := v.Type() |
|
if tp.Kind() == reflect.Ptr { |
|
v = v.Elem() |
|
tp = tp.Elem() |
|
} |
|
if tp.Kind() != reflect.Struct || !v.IsValid() { |
|
return |
|
} |
|
|
|
for i := 0; i < tp.NumField(); i++ { |
|
fn := strings.ToLower(tp.Field(i).Name) |
|
if fn == name { |
|
res = v.Field(i) |
|
ok = true |
|
return |
|
} |
|
|
|
if vres, vok := getFieldByName(v.Field(i), name); vok { |
|
ok = vok |
|
res = vres |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
//MiddleAggregate 处理聚合逻辑 |
|
type MiddleAggregate struct { |
|
Cfg []*Aggregate |
|
Encode bool |
|
} |
|
|
|
//Process handle multi aggregate logists |
|
func (m *MiddleAggregate) Process(data interface{}) { |
|
cfgs := []*Aggregate{} |
|
for _, item := range m.Cfg { |
|
if item.Type == TypeMiddleAll || (m.Encode && item.Type == TypeMiddleEncode) || (!m.Encode && item.Type == TypeMiddleDecode) { |
|
cfgs = append(cfgs, item) |
|
} |
|
} |
|
if len(cfgs) == 0 { |
|
return |
|
} |
|
|
|
sort.Sort(AggregateArr(cfgs)) |
|
for _, item := range cfgs { |
|
item.Process(data, m.Encode) |
|
} |
|
} |
|
|
|
//AggregateArr arr |
|
type AggregateArr []*Aggregate |
|
|
|
//Len . |
|
func (f AggregateArr) Len() int { |
|
return len(f) |
|
} |
|
|
|
//Less . |
|
func (f AggregateArr) Less(i, j int) bool { |
|
return f[i].Order < f[j].Order |
|
} |
|
|
|
//Swap . |
|
func (f AggregateArr) Swap(i, j int) { |
|
f[i], f[j] = f[j], f[i] |
|
}
|
|
|