分佈式系列三: 對象序列化

序列化能夠解決分佈式系統節點間複雜對象傳輸的問題. 將對象狀態轉化爲可存儲或可傳輸的過程叫序列化, 而反序列化是將其還原成對象的過程.html

幾種序列化機制

JDK的序列化

Java默認的序列化要求實現Serializable接口.java

缺點:web

  1. 序列化的結果比較大, 佔用字節多, 傳輸效率低
  2. 僅Java實現, 不能跨語言

WebService

基於XML格式的傳輸.json

Json方式

缺點:設計模式

  1. 結果依然較大
  2. 性能低

二進制傳輸

MessagePack
Protocal Bufferapp

Java的默認方式

// 使用了lombok
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Car implements Serializable{

    // 版本號, java經過此版本號是否一致判斷是否能夠執行反序列化
    // 名稱的數據類型必須準確,不然只是至關於定義一個普通的靜態變量
    public static long serialVersionUID = -1244L;

    // 靜態變量不序列化
    public static int age = 10;

    // 用protobuffer的話, 須要field上加Protobuffer的註解
    @Protobuf(fieldType = FieldType.INT32,order = 1)
    private int wheels;
    @Protobuf(fieldType = FieldType.STRING,order = 2)
    private String name;

    // 瞬時變量, 不被序列化
    private transient String desc;

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //serializeCar();
        Car car = deSerializeCar();
        System.out.println(car.age);
        System.out.println(car.toString());
    }

    private static void serializeCar() throws IOException {
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File("car")));
        Car car = new Car(4, "BMW", "fast....");
        objectOutputStream.writeObject(car);
        car.age = 12;
        objectOutputStream.close();
    }

    private static Car deSerializeCar() throws IOException, ClassNotFoundException {
        ObjectInputStream objectInputStream;
        objectInputStream = new ObjectInputStream(new FileInputStream(new File("car")));
        Car car = (Car) objectInputStream.readObject();
        return car;
    }
}
  1. static final long serialVersionUID = -124L; 序列化版本號, 一致的版本才能夠反序列化
  2. 靜態變量不參與序列化
  3. transient 修飾的變量不序列化
  4. 父類實現序列化接口,子類會繼承; 子類實現但父類不實現, 則父類的字段不被序列化(代碼略)
  5. 序列化對象的存儲: 同一對象的序列化,第二次將只存儲第一個的引用及變化的部分,這樣能夠節省空間(代碼略)
  6. 實現深克隆, 參看設計模式五: 原型模式(Prototype)

經常使用序列化協議

  • Json: Json是比較流行的序列化機制, Spring 默認的json序列化是使用Jackson, 阿里的FastJson效率更高且更易於使用.
  • Protobuffer: 二進制序列化有性能和傳輸方面的優點. 還有MessagePackage
  • Hessian2, Dobbo使用此協議
  • XML
  • FST
// FastJson的序列化和反序列化
String strJson = JSON.toJSONString(object);
Object object = JSON.parse(text);

//Hessian的序列化
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Hessian2Output hessian2Output = new Hessian2Output(byteArrayOutputStream);
hessian2Output.writeObject(object);

//Protobuffer的序列化
Codec<Car> carCodec = ProtobufProxy.create(Car.class, false);
byte[] bytes = carCodec.encode(object);

序列化須要引用相關的包, 下面列出幾個.分佈式

<!--jackson的序列化包-->
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

<!--fastjson的序列化包-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.49</version>
</dependency>

<!--Protobuffer的序列化包,由百度封裝,增長了易用性-->
<dependency>
    <groupId>com.baidu</groupId>
    <artifactId>jprotobuf</artifactId>
    <version>2.2.5</version>
</dependency>

<!--hessian的序列化包-->
<dependency>
    <groupId>com.caucho</groupId>
    <artifactId>hessian</artifactId>
    <version>4.0.51</version>
</dependency>
相關文章
相關標籤/搜索