今天踩的Dubbo的序列化对象的一个坑

本文记录了一次在使用Dubbo时遇到的序列化对象坑洞,问题源于消费者和服务提供者端的类路径不一致导致的反序列化错误。作者深入探讨了不同路径、序列化方式以及对象属性相同情况下可能出现的问题,并通过实验验证了Hessian和Java序列化在处理serialVersionUID不一致时的行为差异。结论是,路径、序列化方式以及对象的序列化实现都会影响反序列化的结果。
摘要由CSDN通过智能技术生成

Dubbo序列化对象的一个坑

​ --洱涷Zz


​ 今天在处理项目问题的时候遇到了Dubbo序列化对象的一个坑,记录一下:

​ 大致是同事在调用Dubbo rpc接口的时候发现返回的值和预期的返回值不符,预期是返回一个对象的集合,但是返回的集合里是hashMap,查看他们代码解决后是发现他们的消费者端对返回对象的路径定义与我们服务提供者端的路径不一致,导致返回的数据和预期不符。这个解决起来很简单,保持路径一致就可以。(最好就是将对象定义成公共的,可以很好的避免这些问题)

​ 但是为什么会出现这种情况呢?为什么会出现这个hashMap呢?

​ 一步一步理下来发现是消费端和服务端在进行类的序列化反序列化时出现的问题,首先Java中进行反序列化的类是JavaSerializer,这个类的构造方法里调用了这样的方法:getFieldMap,把里面本类和父类的所有方法放在fieldMap里,因为是hashMap,为了保证方法名不覆盖,这个里面就做了一个操作就是:

fieldMap.get(field.getName())!=null;

​ 在消费者端进行反序列化时,会判断该路径下类名是否存在,如果存在,那么就对返回的集合对象进行循环赋值,如果不存在则会直接返回这个hashMap

​ 于此,问题的原因找到了,但是思考一下:

  • 既然是序列化的问题,那么如果是消费端和服务端的对象处于相同路径下,其序列化产生的uid不同会造成什么问题呢?
  • 如果是不同路径下,序列化的uid相同会产生什么问题?
  • 如果是相同路径下,对象还有父对象且其中部分属性相同,会有什么问题?
  • 如果是对象路径、uid、属性都相同但是没有实现序列化会有什么问题?

结论:

  • 由上述反序列化时所调用的方法可知,其在反序列化时是根据方法名和路径去进行匹配赋值的,只要路径相同,名称相同,无论uid是什么,都可以成功返回对象集合,

    • 继续引深,为什么呢?按照java应该是不可以实现的

    • 开始困扰了好久,查资料看到一句话,“hessian2序列化:hessian是一种跨语言的高效二进制序列化方式。但这里实际不是原生的hessian2序列化,而是阿里修改过的hessian lite,它是dubbo RPC默认启用的序列化方式。”。后来就想,是不是因为序列化方式有关,会不会是Hessian序列化时并不会在意serialVersionUID的变化。为证实心中的疑虑。分别采用了Hessian和java两种序列化方式进行验证。

    • 这里有2个工程,一个发送端,一个接收端,采用SpringBoot启动,两个工程里面都分别载入了实体对象Person。用于测试对象serialVersionUID相同和不相同的情况。

    • 1.第一个工程,是传输对象接受端,这里反序列化。serializabletest-server。3个主类
      1.1.Person.java 传输对象。

      @ToString
      @Data
      public class Person implements Serializable {
             
      private static final long serialVersionUID = -1923645274767028479L;
      private String[] address;
      private String name;
      private int phone;
      }
      

      1.2. HessianController.java hessian反序列化接受类。通过一个Controller接受http提交过来的对象信息

      @Slf4j
      @RestController
      @RequestMapping("/hessian")
      public class HessianController {
             
          
          @RequestMapping(value = "/hello")
          public String helloWorld(HttpServletRequest request, HttpServletResponse response) throws IOException {
             
              log.info("hessian反序列化开始------------------------");
              ServletInputStream sis = request.getInputStream();
              Hessian2Input h2i = new Hessian2Input(sis)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值