hession 源码解析 自定义序列化器

Posted xiaoliuliu2050

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hession 源码解析 自定义序列化器相关的知识,希望对你有一定的参考价值。

  1. 背景

    最近在处理一个hessian的反序列化问题时,因为服务端使用了pojo bean中多了一个enum属性,导致客户端在反序列化时疯狂的在打印日志。警告说找不到对应的enum class,因为项目中本身是设置了log4j的根输出为一个文件。 

    比较奇怪的是,hessian对应的日志输出全都打印到了控制台(虽然我们对console进行了重定向输出),导致对应的文件达到几百MB。无奈之下,仔细分析了下hessian的源码。

介绍

 

先看一张hessian主要的几个概念图

说明:

 

  1. Serializer  序列化的接口
  2. Deserializer 反序列化的接口
  3. AbstractHessianInput  hessian自定义的输入流,提供对应的read各种类型的方法
  4. AbstractHessianOutput  hessian自定义的输出流,提供对应的write各种类型的方法

 

AbstractSerializerFactory介绍

serializerFactory从字面意思上也看的出来,是管理和维护对应序列化/反序列化机制的工厂。默认的几种实现

 

  • SerializerFactory 标准的实现
  • ExtSerializerFactory 我们可以设置自定义的序列化机制,通过该Factory可以进行扩展。
  • BeanSerializerFactory 对SerializerFactory的默认object的序列化机制进行强制指定,指定为BeanSerializer。 具体BeanSerializer的实现后面再表。

自定义序列化机制的扩展:

  1. 实现Serializer/Deserializer接口
1.ExtSerializerFactory extSerializerFactory = new ExtSerializerFactory();  
2.extSerializerFactory.addSerializer(class , mySerializer); //添加自定义的序列化接口  
3.extSerializerFactory.addDeserializer(class , myDeserializer); //添加自定义的反序列化接口  
4.  
5.serializerFactory.addFactory(extSerializerFactory); //注册ext到序列化工厂  

 

SerializerFactory介绍:

先看一下hesian提供的Serializer/Derializer几种默认实现

 



 


 

 

具体的实现就不细说,有兴趣的自己看代码去。

下面提一下我在看得过程中比较在意和疑惑过的点。

 

1.  Object对象的序列化/反序列化

答:JavaSerializer或者BeanSerializer。这两者的区别

 

  • JavaSerializer是通过反射获取所有bean的属性进行序列化,排除static和transient属性,对其他所有的属性进行递归序列化处理(比如属性本身是个对象)。
  • BeanSerializer是遵循pojo bean的约定,扫描bean的所有方法,发现存在get和set方法的属性进行序列化,它并不直接直接操作所有的属性,比较温柔。 注意:BeanSerializer将会无法处理你的boolean属性,因为通过默认的eclipse生成的方法是以isXXX打头,不会被序列化。

2.  枚举对象的序列化/反序列化

答:看过类图后,就很明显的发现存在一个EnumSerializer和EnumDeserializer实现。大家都知道枚举对象全都继承于enum对象,所以EnumSerializer会反射调用name方法,EnumDeserializer是反射调用valueof方法。这样就很明显了,如果服务端多了一个枚举值定义,客户端反序列化会出现异常,不会是一个兼容的过程。

 

补充:测试过程中,hessian 3.1.3版本存在enum序列化问题,低级的问题。

 

3.  服务端抛异常后的序列化/反序列化

答:这个也是在做rpc调用,一个比较容易被遗忘的点,只关注了正常的业务功能的流程,却没有考虑对应的异常处理的序列化和反序列化。hessian提供了ThrowableSerializer和StackTraceElementDeserializer进行序列化处理。

  • ThrowableSerializer会按照object的序列化方式,传递对应的信息到客户端。包括stackTrace和detailMessage等。
  • StackTraceElementDeserializer反序列化对应的异常栈信息。异常的其他属性通过JavaSerializer进行反序列化处理。

补充:测试过程中,hessian 3.0.20,3.1.3版本存在问题,异常的反序列化在hessian 1.0协议是正常的,到2.0就会出现错误。 具体的问题也有人报告了bug : http://maillist.caucho.com/pipermail/hessian-interest/2008-February/000297.html ,升级到3.1.5之后就解决了.

 

测试代码

1.public static void exceptionTest() throws Exception   
2.    Exception exception = null;  
3.    try   
4.        FileInputStream stream = new FileInputStream("notfound");  
5.     catch (FileNotFoundException e)   
6.        exception = e;  
7.      
8.  
9.    ByteArrayOutputStream bos = new ByteArrayOutputStream();  
10.    HessianOutput out = new HessianOutput(bos);  
11.    out.writeObject(exception);  
12.    out.flush();  
13.  
14.    byte[] bytes = bos.toByteArray();  
15.    ByteArrayInputStream bin = new ByteArrayInputStream(bytes);  
16.    HessianInput in = new HessianInput(bin);  
17.    Exception read = (Exception) in.readObject(FileNotFoundException.class);  
18.    read.printStackTrace();  
19.    System.out.println(read);  
20.  


hessian支持对流进行压缩处理,可以看下 Deflation

1.Hessian2Output out = new Hessian2Output(bos);  
2.out = envelope.wrap(out); //包装为压缩  
3.  
4.Hessian2Input in = new Hessian2Input(bin);  
5.in = envelope.unwrap(in); //解缩

 

压缩慎用,在测试过程中有一些磕磕碰碰的小问题。 

 

后记

hessian序列化机制的性能比较,后续补上。 主要是和原先的几种序列化协议相关数据对比

 

 

序列化数据对比


bytes字节数对比


 

具体的数字: 

 protobufjacksonxstreamSerializablehessian2hessian2压缩hessian1
序列化(单位ns)11545421 92406 101892679410076629027
反序列化(单位ns)13348743 117329 640273787118843237596
bytes97311 664 824374283495

 

版权声明:本文内容由互联网用户自发贡献,版权归作者所有,本社区不拥有所有权,也不承担相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:yqgroup@service.aliyun.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

以上是关于hession 源码解析 自定义序列化器的主要内容,如果未能解决你的问题,请参考以下文章

springboot源码解析-自定义系统初始化器

Gson源码解析

Gson源码解析

springmvc自定义参数解析器/类型转换器

什么是迭代器,Python迭代器及其用法

Cf序列化器-Serializer解析