diff --git a/common/constant/default.go b/common/constant/default.go index 05461ca6e7360e08d716d6b78d20ad4411df99e8..7ab92249ad742152b385ac7f0aa6e96f37fdb00c 100644 --- a/common/constant/default.go +++ b/common/constant/default.go @@ -38,6 +38,8 @@ const ( PREFIX_DEFAULT_KEY = "default." DEFAULT_SERVICE_FILTERS = "echo" DEFAULT_REFERENCE_FILTERS = "" + GENERIC_REFERENCE_FILTERS = "generic" + GENERIC = "$invoke" ECHO = "$echo" ) diff --git a/config/reference_config.go b/config/reference_config.go index 0ab24e184a54f58da134c7b3c66b0611ec1e73b8..c1565004c0bf12b5546f703f6b6529c438afd4fa 100644 --- a/config/reference_config.go +++ b/config/reference_config.go @@ -170,7 +170,7 @@ func (refconfig *ReferenceConfig) getUrlMap() url.Values { //filter urlMap.Set(constant.REFERENCE_FILTER_KEY, mergeValue(consumerConfig.Filter, refconfig.Filter, constant.DEFAULT_REFERENCE_FILTERS)) - + urlMap.Set(constant.REFERENCE_FILTER_KEY, mergeValue(consumerConfig.Filter, refconfig.Filter, constant.GENERIC_REFERENCE_FILTERS)) for _, v := range refconfig.Methods { urlMap.Set("methods."+v.Name+"."+constant.LOADBALANCE_KEY, v.Loadbalance) urlMap.Set("methods."+v.Name+"."+constant.RETRIES_KEY, strconv.FormatInt(v.Retries, 10)) diff --git a/filter/impl/generic_filter.go b/filter/impl/generic_filter.go new file mode 100644 index 0000000000000000000000000000000000000000..14da6eeabe1395c01db4d4e9ddfcc18a44495681 --- /dev/null +++ b/filter/impl/generic_filter.go @@ -0,0 +1,75 @@ +package impl + +import ( + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/filter" + "github.com/apache/dubbo-go/protocol" + invocation2 "github.com/apache/dubbo-go/protocol/invocation" + "reflect" + "strings" +) + +const ( + GENERIC = "generic" +) + +func init() { + extension.SetFilter(GENERIC, GetGenericFilter) +} + +// when do a generic invoke, struct need to be map + +type GenericFilter struct{} + +func (ef *GenericFilter) Invoke(invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { + if invocation.MethodName() == constant.GENERIC { + var newArguments = invocation.Arguments() + for i := range newArguments { + newArguments[i] = Struct2MapAll(newArguments[i]) + } + newInvocation := invocation2.NewRPCInvocation(invocation.MethodName(), newArguments, invocation.Attachments()) + return invoker.Invoke(newInvocation) + } + return invoker.Invoke(invocation) + +} + +func (ef *GenericFilter) OnResponse(result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { + return result +} + +func GetGenericFilter() filter.Filter { + return &GenericFilter{} +} +func Struct2MapAll(obj interface{}) map[string]interface{} { + t := reflect.TypeOf(obj) + v := reflect.ValueOf(obj) + result := make(map[string]interface{}) + if reflect.TypeOf(obj).Kind() == reflect.Struct { + for i := 0; i < t.NumField(); i++ { + if v.Field(i).Kind() == reflect.Struct { + if v.Field(i).CanInterface() { + result[headerAtoa(t.Field(i).Name)] = Struct2MapAll(v.Field(i).Interface()) + } else { + println("not in to map,field:" + t.Field(i).Name) + } + } else { + if v.Field(i).CanInterface() { + if tagName := t.Field(i).Tag.Get("m"); tagName == "" { + result[headerAtoa(t.Field(i).Name)] = v.Field(i).Interface() + } else { + result[tagName] = v.Field(i).Interface() + } + } else { + println("not in to map,field:" + t.Field(i).Name) + } + } + } + } + return result +} +func headerAtoa(a string) (b string) { + b = strings.ToLower(a[:1]) + a[1:] + return +}