使用dubbo自定义返回对象异常

来源:互联网 发布:华硕笔记本怎么样 知乎 编辑:程序博客网 时间:2024/06/05 15:43

最近修改了dubbo服务端的返回对象,引用了spring-data-commons中的Page接口,还是使用默认的dubbo协议,也就是netty+hessian2;当消费端连接过来获取数据时,报了下面这个异常

Caused by: com.alibaba.com.caucho.hessian.io.HessianProtocolException: 'org.springframework.data.domain.PageImpl' could not be instantiated    at com.alibaba.com.caucho.hessian.io.JavaDeserializer.instantiate(JavaDeserializer.java:275)    at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:155)    at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObjectInstance(Hessian2Input.java:2067)    at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:1592)    at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:1576)    at com.alibaba.com.caucho.hessian.io.JavaDeserializer$ObjectFieldDeserializer.deserialize(JavaDeserializer.java:396)    ... 29 more

上网查过后发现hessian反序列化:

参数及返回值需实现Serializable接口
参数及返回值需有无参构造函数(可以是private的)或者有参构造所有函数允许传入null值。

而Page接口的实现类PageImpl继承的抽象父类Chunk并未提供无参构造函数,也可以通过查看源码com.alibaba.com.caucho.hessian.io.JavaDeserializer

/**   * Creates a map of the classes fields.   */  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();  }

由于PageImpl的两个构造函数的参数都不是基本类型,因此_constructorArgs所包含的值全部是null。

知道问题所在了,那么我们只需更改传输的序列化方式,下面给出两种解决方案让我们还可以用到spring-data-commons中的Page接口:

1、dubbo的序列化使用除了hessian2的其他序列化方式,测试的序列化框架有kryo、fastJson,发现如果用fastJson作为序列化的话,不报错能正常返回,但是data数据是空的;所以推荐使用kryo,也是一种非常高效的序列化框架,其他的可以自行测试。dubbo自带实现有的序列化方式在包com.alibaba.dubbo.common.serialize.support下,当然你也参考官方文档自行实现序列化扩展,比如protobuf。
序列化扩展示例
dubbo自带

服务端dubbo增加配置如下:

<dubbo:protocol name="dubbo" port="20088" serialization="kryo"/>

客户端dubbo增加配置如下:

<dubbo:protocol serialization="kryo"/>

2、改用其他协议,比如rmi,hessian,http
服务端dubbo修改配置如下:

<dubbo:protocol name="rmi" port="1090"/><dubbo:protocol name="hessian" port="8282"/><!-- 下面就可以引用传输协议了 --><dubbo:service interface="xxx.xx.x.TestService" ref="testService" protocol="hessian,rmi"/>

客户端dubbo修改配置如下:

<!-- protocol可选服务端提供的hessian,rmi --><dubbo:reference id="testService" interface="xxx.xx.x.TestService" protocol="hessian"/>

推荐第一种,毕竟默认的dubbo协议还是在数据小但是高并发的情况下有优势的。

0 0
原创粉丝点击