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

最近修改了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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值