weibocom / motan

A cross-language remote procedure call(RPC) framework for rapid development of high performance distributed services.
Other
5.89k stars 1.78k forks source link

如何自定义motan yar协议的序列化规则 #572

Open JerryChaox opened 7 years ago

JerryChaox commented 7 years ago

框架里用到了hibernate的懒加载,每当序列化时,hibernate的持久化的session已经关闭了,但同时序列化又访问了该懒加载的属性,导致了错误。

如何自定义yar协议序列化规则,例如当访问到的属性是hibernate的代理类时不进行序列化

JerryChaox commented 7 years ago
if (value instanceof HibernateProxy) {//hibernate代理对象
      LazyInitializer initializer = ((HibernateProxy) value).getHibernateLazyInitializer();
      if (initializer.isUninitialized()) {
        return false; //不采取序列化操作
      }
} else if (value instanceof PersistentCollection) {//实体关联集合一对多等
      PersistentCollection collection = (PersistentCollection) value;
      if (!collection.wasInitialized()) {
        return false; //不采取序列化操作
      }
      Object val = collection.getValue();
      if (val == null) {
        return false; //不采取序列化操作
      }
    }
    return true; //采取序列化操作
  }

自定义代码

rayzhang0603 commented 7 years ago

yar协议序列化是在yar-java 包中实现的,这个包不适合依赖hibernate。 建议的方法是通过实现一个filter扩展,来对motan response中的返回结果进行hibernate的代理类转换。实现filter扩展可以参考motan扩展机制, 以及com.weibo.api.motan.filter包下的一些具体filter实现。

JerryChaox commented 7 years ago

@rayzhang0603 配置了一下filter扩展,可是好像不起作用

com.hftkeji.server.filter.HibernateClassFilter:

package com.hftkeji.server.filter;
@SpiMeta(name = "HibernateClassFilter")
@Activation(sequence = 1)
public class HibernateClassFilter implements Filter{

    @Override
    public Response filter(Caller<?> caller, Request request) {
        Response rs = caller.call(request);
        System.out.println("---------------------------" + rs.getValue());
        return rs;
    }
}

META-INF/services/com.weibo.api.motan.filter.Filter

com.hftkeji.server.filter.HibernateClassFilter

这样配置有什么问题吗?结果是没有加载到这个模块。

rayzhang0603 commented 7 years ago

@JerryChaox filter默认是不生效的,如果需要强制生效,可以通过配置@Activation来实现,MotanConstants.NODE_TYPE_SERVICE表示在server端强制生效,MotanConstants.NODE_TYPE_REFERER表示在client端强制生效。 强制生效情况下,不管任何service都会进行filter过滤。 配置样例如下:

@Activation(key = { MotanConstants.NODE_TYPE_SERVICE, MotanConstants.NODE_TYPE_REFERER })

如果只需要在某些service中生效,则可以直接通过在basicService或者service中配置 filter="myfilter_name"即可,其中的myfilter_name就是你声明的@SpiMeta(name = "HibernateClassFilter")中name的值

推荐通过配置方式使用filter,减少不必要的filter装载

JerryChaox commented 7 years ago

@rayzhang0603 感谢指导,配置生效了。但是如何在序列化之前获取reponse对应的返回对象呢,调用response.getValue() 方法后,不知道为什么就没有序列化的异常了,客户端收到UNKNOWN:0

rayzhang0603 commented 7 years ago

server端filter生效的位置就是在序列化之前,你在server端获取到response的value后可以打印出value看看,或者直接在filter处debug吧,这样观察返回值比较直观