123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- 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]
- }
|