對象序列化


在分布式系統,任何數據都要轉化為二進制流在網絡上進行傳輸,在面向對象設計中,我們經常會面臨如何將定義好的對象發送到遠端的問題,換言之,問題精確為發送方如何將對象轉化為二進制流,接收方如何將二進制數據流轉化為對象。將對象轉換為二進制流的過程稱之為對象序列化,反之將二進制流恢復為對象的過程稱為反序列化。

目前成熟的解決方案包括: 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

今天主要和大家分享了序列化的一些基本知識和技巧,希望對大家有所幫助。本文的主要參考來源於大型分布式網站架構設計與實踐這本書,今后一段時間里的博文將會以這本書作為主要參考來源。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM