Dubbo, Hessian 序列化注意事项
  TEZNKK3IfmPf 2024年03月22日 25 0

最近遇到一个问题,B 服务调用 A 服务时,返回值反序列化时,POJO对象变成了Map类型。在A服务单独测试的时候一直还原不了,在 B 服务进行测试的时候,跟到反序列化数据时才看到原因。

A 服务的接口方法返回的结果是一个Object(或 ​Map<String, Object>​ 中的 ​value​),​Object​ 的具体实现不在 A 服务的 API 包中,因此在 B 服务找不到该返回值真正的实现类,在 B 服务调用接口返回结果反序列化找不到具体的类型时,就会以 ​Map​ 类型进行实例化。

下面是简单接口示例:
在 ​​​A-api​​ 模块中:

public interface A {
/* 注意是 Object(或 `Map<String, Object>` 中的 `value`) */
Object say();
}

在 ​​A-service​​ 实现中:

public class AModel implements Serializable {
private static final long serialVersionUID = 1L;
private String text;
/* 省略 getter setter */
}

public class AImpl implements A {
public Object say() {
return new AModel("hello");
}
}

在 ​​B-service​​​ 中用到了 ​​A-api​​​,但是不依赖 ​​A-service​​:

public class BImpl implements B {
@Autowire
private A a;

public void saySomething() {
Object s = a.say();
//强制转换会出错,实际的返回值类型为HashMap
AModel am = (AModel)s;
//可以下面这样调用,真正使用时这样肯定也算错误
String text = ((HashMap)am).getText();
}
}

下面是简单的分析过程。

反序列化过程:

从 ​​Hessian2Input​​​ 开始,反序列 Object 时调用 ​​readObjectInstance​​:

Dubbo, Hessian 序列化注意事项

 

上图代码中,会从 ​​SerializerFactory.getObjectDeserializer​​ 获取类型对应的反序列化实现。

Dubbo, Hessian 序列化注意事项

 

通过一层层调用,最后到下面的方法:

Dubbo, Hessian 序列化注意事项

 

在该方法中,有如下代码:

Dubbo, Hessian 序列化注意事项

 

上面会反射查找类,找到就能正确的反序列化为真正的对象,如果找不到,继续看后面的代码。

可以看到这里有警告日志,这里需要特别的设置才能输出日志。
首先,这里的 log 是 ​​​java.util.Logger​​​ 实现,目前流行的日志框架一般都选择 ​​slf4j​​ 作为日志的中间层,这时可以通过下面依赖从 jul 桥接到 slf4j:

<dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>1.7.28</version> </dependency>

相关文档:​​Bridging legacy APIs​​

有了上面的依赖后,就能按照 ​​slf4j​​ 的方式进行输出。

回到外层代码,如下:

Dubbo, Hessian 序列化注意事项

 

找不到类型对应的序列化实例时,就会使用 ​​MapDeserializer​​​ 进行反序列化。 ​​MapDeserializer​​ 中的方法如下:

Dubbo, Hessian 序列化注意事项

 

至此就完全清楚 Dubbo 中反序列化的一条重要原则了。

接口中返回的 POJO 如果是个接口,如果需要正确反序列化,那么实现类一定要能访问到。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2024年03月22日 0

暂无评论

TEZNKK3IfmPf