对象序列化

214 阅读2分钟

分布式系列三: 对象序列化 序列化可以解决分布式系统节点间复杂对象传输的问题. 将对象状态转化为可存储或可传输的过程叫序列化, 而反序列化是将其还原成对象的过程.

几种序列化机制 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 修饰的变量不序列化 父类实现序列化接口,子类会继承; 子类实现但父类不实现, 则父类的字段不被序列化(代码略) 序列化对象的存储: 同一对象的序列化,第二次将只存储第一个的引用及变化的部分,这样可以节省空间(代码略) 实现深克隆, 参看设计模式五: 原型模式(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 carCodec = ProtobufProxy.create(Car.class, false); byte[] bytes = carCodec.encode(object); 序列化需要引用相关的包, 下面列出几个.

org.codehaus.jackson jackson-mapper-asl 1.9.13 com.alibaba fastjson 1.2.49 com.baidu jprotobuf 2.2.5 com.caucho hessian 4.0.51