hessian序列化原理分析

1. hessian序列化举例

1.1 hessian协议简介
1.1.1 特点

参考官方文档的描述,下面做一些简要描述,http://hessian.caucho.com/doc/hessian-serialization.html。

  • 它必须自我描述序列化类型,即不需要外部模式或接口定义
  • 它必须是独立于语言的,包括支持脚本语言
  • 它必须是可以通过单一方式进行读写
  • 它必须尽可能紧凑
  • 它必须简单,这样才能有效地测试和实现
  • 必须尽可能地快
  • 它必须支持Unicode字符串
  • 它必须支持8位二进制数据,而不需要转义或使用附件
  • 它必须支持加密、压缩、签名和事务上下文信封
1.1.2 hessian语法简介

以下几种示例,更多参考:http://hessian.caucho.com/doc/hessian-serialization.html。

        #boolean true/false
boolean ::= 'T'
        ::= 'F'
          
        # list/vector
list    ::= 'V' type? length? value* 'z'
        ::= 'v' int int value*          #第一个int表示类型引用, 第二个int表示长度
          

        #32-bit 有符号整型(比如0x90编码为0int     ::= 'I' b3 b2 b1 b0
        ::= [x80-xbf]                   #-x10 to x3f
        ::= [xc0-xcf] b0                #-x800 to x7ff
        ::= [xd0-xd7] b1 b0             #-x40000 to x3ffff
1.2 hessian序列化与反序列化举例
public static void serialize1(Student student){
  FileOutputStream fileOutputStream;
  try {
    fileOutputStream = new FileOutputStream("/Users/zhuqiuhui/Desktop/studentHession.txt");
    // 从对象中获取字节流
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    Hessian2Output output = new Hessian2Output(os);
    output.writeObject(student);
    output.getBytesOutputStream().flush();
    output.completeMessage();
    output.close();

    // 写入到文件中
    fileOutputStream.write(os.toByteArray());
  } catch (Exception e) {
    e.printStackTrace();
  }
}

public static Student deserialize1(){
  FileInputStream fileInputStream;
  Object result = null;
  try {
    fileInputStream = new FileInputStream("/Users/zhuqiuhui/Desktop/studentHession.txt");
    byte[] data = new byte[1024];
    int len = fileInputStream.read(data);
    System.out.println("read byte length:" + len);

    // 从流中读出对象
    ByteArrayInputStream is = new ByteArrayInputStream(data);
    Hessian2Input input = new Hessian2Input(is);
    result = input.readObject();
  } catch (Exception e) {
    e.printStackTrace();
  }
  return (Student)result;
}

public static void main(String[] args) {

  Student student = new Student();
  student.setId("123");
  student.setName("方辰");

  // 序列化
  // serialize1(student);

  // 反序列化
  Student serializestudent = deserialize1();
  System.out.println("deserialize result entity id is "+serializestudent.getId());
  System.out.println("deserialize result entity name is "+serializestudent.getName());
}
1.3 hessian协议与jdk区别
  • 区别一:java序列化无法跨语言
  • 区别二:新旧对象的版本Java通过一个serialVersionUID来关联,需要开发者关注序列化的语义
  • 区别三:java序列化不支持加密
  • 区别四:Java序列化的内容比hessian大

2. hessian序列化分析

2.1 hessian序列化必须 serialVersionUID 吗?

hessian序列化对象不用增加serialVersionUID,hessian序列化时把类的描述信息写入到byte[]中

2.2 hessian序列化与反序列化源码分析
2.2.1 (反)序列化器的对应关系
类型序列化器反序列化器
CollectionCollectionSerializerCollectionDeserializer
MapMapSerializerMapDeserializer
IteratorIteratorSerializerIteratorDeserializer
AnnotationAnnotationSerializerAnnotationDeserializer
InterfaceObjectSerializerObjectDeserializer
ArrayArraySerializerArrayDeserializer
EnumerationEnumerationSerializerEnumerationDeserializer
EnumEnumSerializerEnumDeserializer
ClassClassSerializerClassDeserializer
默认JavaSerializerJavaDeserializer
ThrowableThrowableSerializer
InputStreamInputStreamSerializerInputStreamDeserializer
InetAddressInetAddressSerializer
2.2.2 为什么序列化对象要 implements Serializable 接口?
// com.caucho.hessian.io.SerializerFactory 序列化时会获取默认序列化器
protected Serializer getDefaultSerializer(Class cl) {
  if (_defaultSerializer != null)
    return _defaultSerializer;

  // 若序列化对象没有实现 Serializable 接口,则会抛出IllegalStateException
  if (! Serializable.class.isAssignableFrom(cl)
      && ! _isAllowNonSerializable) {
    throw new IllegalStateException("Serialized class " + cl.getName() + " must implement java.io.Serializable");
  }

  if (_isEnableUnsafeSerializer
      && JavaSerializer.getWriteReplace(cl) == null) {
    return UnsafeSerializer.create(cl);
  }
  else
    return JavaSerializer.create(cl);
}
2.2.3 序列化过程与反序列化过程
  • 序列化过程:Hessian2Output -> SerializerFactory -> Serializer
  • 反序列化过程:Hessian2Input -> SerializerFactory -> Deserializer
2.3 总结
  • 序列化对象要实现 Serializable 接口,否则序列化时会报“must implement java.io.Serializable”异常
  • 若序列化对象经hessian序列化后,序列化对象中不加serialVersionUID时,再改变(增加对象属性、删除对象属性)都不会产生反序列化异常,即hessian序列化对象不再需要serialVersionUID
  • hessian会把复杂对象所有属性存储在一个 Map 中进行序列化。所以在父类、子类存在同名成员变量的情况下, Hessian 序列化时,先序列化子类,然后序列化父类,因此反序列化结果会导致子类同名成员变量被父类的值覆盖。
  • hessian中的writeReplace方法与readResolve方法的作用一样,如果序列化的对象具有此方法,会利用此方法返回的实例来代替序列化后实例,用以保证对象的单例性
  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bboyzqh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值