关于Dubbo默认序列化Hessian的问题

项目中使用了服务框架Dubbo进行远程调用,框架持久层使用的是Spring data jpa,一同事开发的Dubbo接口类似入如下:

XXXXService.findBy(PageRequest pg );其中PageRequest 是spring data jps提供的分页排序实现类。

当在客户端调用该接口时,PageRequest 中明明传入的油蚕丝,但一到Dubbo反序列化,Dubbo

总时抛  PageRequest  could not be instantiated;跟了下Dubbo的源码,发现这个异常是在

JavaDeserializer(Dubbo序列化类)中抛出的,再看异常cause by,发现是 PageRequest的

父类AbstractPageRequest 构造函数检查失败出的问题,
public AbstractPageRequest(int page, int size) {

if (page < 0) {
throw new IllegalArgumentException("Page index must not be less than zero!");
}

if (size < 1) {
throw new IllegalArgumentException("Page size must not be less than one!");
}

this.page = page;
this.size = size;
}
就红的地方抛出类异常,也就是说size=0啦。很奇怪,明明出入的PageRequest有值,为啥Dubbo反序列就把变成零了,带着这个问题,有跟了一遍Dubbo源码,发现在JavaDeserializer
public JavaDeserializer(Class cl)
  {
    _type = cl;
    _fieldMap = getFieldMap(cl);

    _readResolve = getReadResolve(cl);

    if (_readResolve != null) {
      _readResolve.setAccessible(true);
    }

    Constructor []constructors = cl.getDeclaredConstructors();
    long bestCost = Long.MAX_VALUE;

    for (int i = 0; i < constructors.length; i++) {
      Class []param = constructors[i].getParameterTypes();
      long cost = 0;

      for (int j = 0; j < param.length; j++) {
cost = 4 * cost;

if (Object.class.equals(param[j]))
  cost += 1;
else if (String.class.equals(param[j]))
  cost += 2;
else if (int.class.equals(param[j]))
  cost += 3;
else if (long.class.equals(param[j]))
  cost += 4;
else if (param[j].isPrimitive())
  cost += 5;
else
  cost += 6;
      }

      if (cost < 0 || cost > (1 << 48))
cost = 1 << 48;

      cost += (long) param.length << 48;

      if (cost < bestCost) {
        _constructor = constructors[i];
        bestCost = cost;
      }
    }

    if (_constructor != null) {
      _constructor.setAccessible(true);
      Class []params = _constructor.getParameterTypes();
      _constructorArgs = new Object[params.length];
      for (int i = 0; i < params.length; i++) {
        _constructorArgs[i] = getParamArg(params[i]);
      }
    }
  }
有对_constructor和 _constructorArgs初始化的过程,大致意思是会调用所有构造函数中参数最少的那个。
也就是会调用PageRequest中
public PageRequest(int page, int size) {
this(page, size, null);
}

再跟到上面标红的地方,也就是_constructorArgs初始化代码
protected static Object getParamArg(Class cl)
  {
    if (! cl.isPrimitive())
      return null;
    else if (boolean.class.equals(cl))
      return Boolean.FALSE;
    else if (byte.class.equals(cl))
      return new Byte((byte) 0);
    else if (short.class.equals(cl))
      return new Short((short) 0);
    else if (char.class.equals(cl))
      return new Character((char) 0);
   else if (int.class.equals(cl))
      return Integer.valueOf(0);
    else if (long.class.equals(cl))
      return Long.valueOf(0);
    else if (float.class.equals(cl))
      return Float.valueOf(0);
    else if (double.class.equals(cl))
      return Double.valueOf(0);
    else
      throw new UnsupportedOperationException();
  }
上面方法加红的部分,答案揭晓,dubbo全返回0了,所有才有了前面的错误Page size must not be less than one!
总结,Dubbo默认使用的是Hessian序列化,具体可以看下Hessian这个序列化框架,若使用Hessian,默认情况下最好都提供一个无参构造函数

你可能感兴趣的:(DUBBO,Hessian、序列化)