文章目录
- 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("方辰");
// 序列化
// 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 (反)序列化器的对应关系
类型 | 序列化器 | 反序列化器 |
Collection | CollectionSerializer | CollectionDeserializer |
Map | MapSerializer | MapDeserializer |
Iterator | IteratorSerializer | IteratorDeserializer |
Annotation | AnnotationSerializer | AnnotationDeserializer |
Interface | ObjectSerializer | ObjectDeserializer |
Array | ArraySerializer | ArrayDeserializer |
Enumeration | EnumerationSerializer | EnumerationDeserializer |
Enum | EnumSerializer | EnumDeserializer |
Class | ClassSerializer | ClassDeserializer |
默认 | JavaSerializer | JavaDeserializer |
Throwable | ThrowableSerializer | |
InputStream | InputStreamSerializer | InputStreamDeserializer |
InetAddress | InetAddressSerializer |
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方法的作用一样,如果序列化的对象具有此方法,会利用此方法返回的实例来代替序列化后实例,用以保证对象的单例性。