分散式系列三: 物件序列化
阿新 • • 發佈:2018-12-10
序列化可以解決分散式系統節點間複雜物件傳輸的問題. 將物件狀態轉化為可儲存或可傳輸的過程叫序列化, 而反序列化是將其還原成物件的過程.
幾種序列化機制
JDK的序列化
Java預設的序列化要求實現Serializable
介面.
缺點:
- 序列化的結果比較大, 佔用位元組多, 傳輸效率低
- 僅Java實現, 不能跨語言
WebService
基於XML格式的傳輸.
Json方式
缺點:
- 結果依然較大
- 效能低
二進位制傳輸
MessagePack Protocal Buffer
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; } }
static final long serialVersionUID = -124L;
序列化版本號, 一致的版本才可以反序列化- 靜態變數不參與序列化
transient
修飾的變數不序列化- 父類實現序列化介面,子類會繼承; 子類實現但父類不實現, 則父類的欄位不被序列化(程式碼略)
- 序列化物件的儲存: 同一物件的序列化,第二次將只儲存第一個的引用及變化的部分,這樣可以節省空間(程式碼略)
常用序列化協議
- 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>