文章目录
1. hessian序列化举例1.1 hessian协议简介1.1.1 特点1.1.2 hessian语法简介
1.2 hessian序列化与反序列化举例1.3 hessian协议与jdk区别
2. hessian序列化分析2.1 hessian序列化必须 serialVersionUID 吗?2.2 hessian序列化与反序列化源码分析2.2.1 (反)序列化器的对应关系2.2.2 为什么序列化对象要 implements Serializable 接口?2.2.3 序列化过程与反序列化过程
2.3 总结
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编码为
0)
int ::= '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("方辰");
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 (反)序列化器的对应关系
类型序列化器反序列化器
CollectionCollectionSerializerCollectionDeserializerMapMapSerializerMapDeserializerIteratorIteratorSerializerIteratorDeserializerAnnotationAnnotationSerializerAnnotationDeserializerInterfaceObjectSerializerObjectDeserializerArrayArraySerializerArrayDeserializerEnumerationEnumerationSerializerEnumerationDeserializerEnumEnumSerializerEnumDeserializerClassClassSerializerClassDeserializer默认JavaSerializerJavaDeserializerThrowableThrowableSerializerInputStreamInputStreamSerializerInputStreamDeserializerInetAddressInetAddressSerializer
2.2.2 为什么序列化对象要 implements Serializable 接口?
protected Serializer
getDefaultSerializer(Class
cl) {
if (_defaultSerializer
!= null
)
return _defaultSerializer
;
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方法的作用一样,如果序列化的对象具有此方法,会利用此方法返回的实例来代替序列化后实例,用以保证对象的单例性。