在分布式系統,任何數據都要轉化為二進制流在網絡上進行傳輸,在面向對象設計中,我們經常會面臨如何將定義好的對象發送到遠端的問題,換言之,問題精確為發送方如何將對象轉化為二進制流,接收方如何將二進制數據流轉化為對象。將對象轉換為二進制流的過程稱之為對象序列化,反之將二進制流恢復為對象的過程稱為反序列化。
目前成熟的解決方案包括: Google的protocal Buffer, Java內置的序列化,Hessian等,以及JSON和XMl。Protol Buffer性能優異,缺點需要編寫proto文件,無法直接使用Java等中的對象。Hessian相比於ProtolBuffer效率稍低,但是對其他語言的支持優良,且性能穩定,比Java的內置序列化機制要高。Java的序列化機制不需要引入第三方包,使用簡單,在對效率要求不是很高的情況下,可以考慮使用。
本文重點講解一下Java內置的序列化方式和基於Java的Hessian序列化方式,代碼實施如下所示
Java的內置序列化code實施代碼
public byte[] Serialize(Object object) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
//將對象寫入到字節數組中進行序列化
objectOutputStream.writeObject(object);
return byteArrayOutputStream.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public Object deSerialize(byte[] bytes) {
//將二進制數組導入字節數據流中
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
try {
//將字節數組流轉化為對象
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
return objectInputStream.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
基於Hession的序列化實施代碼
使用Hession進行序列化,需要引入Hessian包,maven添加如下依賴:
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
public byte[] Serialize(Object object) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//Hession的序列化
HessianOutput hessianOutput = new HessianOutput(byteArrayOutputStream);
try {
hessianOutput.writeObject(object);
return byteArrayOutputStream.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public Object deSerialize(byte[] bytes) {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
HessianInput hessianInput = new HessianInput(byteArrayInputStream);
try {
return hessianInput.readObject();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
代碼測試
測試代碼如下所示,分別對上面兩種方式進行junit測試,使用的測試對象Employee實現Serializable接口。
@Test
public void should_serialize_and_deserizlie_when_apply_java_serialize() throws Exception {
//given
SerialSample serialSample=new SerialSample();
Employee employee=new Employee("xiaoya",1);
//when
byte[] serialize = serialSample.Serialize(employee);
Employee result = (Employee) serialSample.deSerialize(serialize);
//then
assertThat(result,is(employee));
}
@Test
public void should_serialize_and_deserizlie_object_when_apply_hession_serialize() throws Exception {
//when
HessionSample hessionSample = new HessionSample();
Employee employee = new Employee("xiaoya", 1);
//given
byte[] serialize = hessionSample.Serialize(employee);
Employee result = (Employee) hessionSample.deSerialize(serialize);
//then
assertThat(result, is(employee));
}
Conclusion
今天主要和大家分享了序列化的一些基本知識和技巧,希望對大家有所幫助。本文的主要參考來源於大型分布式網站架構設計與實踐這本書,今后一段時間里的博文將會以這本書作為主要參考來源。
