2019独角兽企业重金招聘Python工程师标准>>>
关于泛化,dubbo文档这样描述的。
http://dubbo.io/User+Guide-zh.htm#UserGuide-zh-%E6%B3%9B%E5%8C%96%E5%BC%95%E7%94%A8
泛接口调用方式主要用于客户端没有API接口及模型类元的情况,参数及返回值中的所有POJO均用Map表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过GenericService调用所有服务实现。
http://dubbo.io/User+Guide-zh.htm#UserGuide-zh-%E6%B3%9B%E5%8C%96%E5%AE%9E%E7%8E%B0
泛接口实现方式主要用于服务器端没有API接口及模型类元的情况,参数及返回值中的所有POJO均用Map表示,通常用于框架集成,比如:实现一个通用的远程服务Mock框架,可通过实现GenericService接口处理所有服务请求。
总的意思来说,某些环境(通用网关、服务端Mock),dubbo接口和类的参数、返回值的类型可能不能加载。为了这些环境也能调用/实现dubbo服务,dubbo框架会对参数和返回值进行泛化(序列)处理,默认处理为Map表示的字符串。虽然文档没有介绍,实际上,dubbo还支持另外两种泛化处理--nativejava(利用java原生序列化)、bean(序列化为JavaBeanDescriptor)。
dubbo通过filter实现泛化:
调用 <-> GenericImplFilter <->网络<->GenericFilter <-> 服务实现
GenericImplFilter和GenericFilter分别在消费者端和提供者端进行序列化的检查和处理。
我们的网关也是直接调用dubbo的,因为dubbo的接口类不能在网关侧加载,所以,需要泛化调用。但是,我们网关调用的dubbo服务的参数和返回值都是通用类型,在网关侧也能加载的。并且,网关侧还需要对返回值进行进一步处理。所以,如果像默认dubbo泛化那样序列化为包含String的Map,那我处理前还需要再反序列化,这比较麻烦(需要确保被反序列化的POJO),性能也不高。
要解决这种问题,可以新增一种泛化类型。
public static final String GENERIC_SERIALIZATION_NOCHANGE = "nochange";
public static boolean isGeneric(String generic) {
return generic != null
&& !"".equals(generic)
&& (Constants.GENERIC_SERIALIZATION_DEFAULT.equalsIgnoreCase(generic) /* 正常的泛化调用 */
|| Constants.GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic) /* 支持java序列化的流式泛化调用 */
|| Constants.GENERIC_SERIALIZATION_BEAN.equalsIgnoreCase(generic)
|| Constants.GENERIC_SERIALIZATION_NOCHANGE.equalsIgnoreCase(generic));
}
并且,GenericFilter中发现如果是这种泛化类型,那么不对服务实现的返回值进行序列化处理。
} else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
return new RpcResult(JavaBeanSerializeUtil.serialize(result.getValue(), JavaBeanAccessor.METHOD));
} else if (ProtocolUtils.isNoChangeGenericSerialization(generic)) {
return new RpcResult(result.getValue());
} else {
return new RpcResult(PojoUtils.generalize(result.getValue()));
}
这样,只要初始化时设置好泛化类型,genericService.$invoke获得的返回值就直接是服务端的值,不是Map等表示的值。
ReferenceConfig
reference.setApplication(application);
reference.setRegistries(registries);
reference.setInterface(serverInterface);
reference.setGeneric(Constants.GENERIC_SERIALIZATION_NOCHANGE);