關於泛化,dubbo文檔這樣描述的。java
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
app
泛接口實現方式主要用於服務器端沒有API接口及模型類元的狀況,參數及返回值中的全部POJO均用Map表示,一般用於框架集成,好比:實現一個通用的遠程服務Mock框架,可經過實現GenericService接口處理全部服務請求。框架
總的意思來講,某些環境(通用網關、服務端Mock),dubbo接口和類的參數、返回值的類型可能不能加載。爲了這些環境也能調用/實現dubbo服務,dubbo框架會對參數和返回值進行泛化(序列)處理,默認處理爲Map表示的字符串。雖然文檔沒有介紹,實際上,dubbo還支持另外兩種泛化處理--nativejava(利用java原生序列化)、bean(序列化爲JavaBeanDescriptor)。ide
dubbo經過filter實現泛化:性能
調用 <-> GenericImplFilter <->網絡<->GenericFilter <-> 服務實現測試
GenericImplFilter和GenericFilter分別在消費者端和提供者端進行序列化的檢查和處理。ui
咱們的網關也是直接調用dubbo的,由於dubbo的接口類不能在網關側加載,因此,須要泛化調用。可是,咱們網關調用的dubbo服務的參數和返回值都是通用類型,在網關側也能加載的。而且,網關側還須要對返回值進行進一步處理。因此,若是像默認dubbo泛化那樣序列化爲包含String的Map,那我處理前還須要再反序列化,這比較麻煩(須要確保被反序列化的POJO),性能也不高。server
要解決這種問題,能夠新增一種泛化類型。
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<GenericService> reference = new ReferenceConfig<GenericService>();
reference.setApplication(application);
reference.setRegistries(registries);
reference.setInterface(serverInterface);
reference.setGeneric(Constants.GENERIC_SERIALIZATION_NOCHANGE);