zoukankan      html  css  js  c++  java
  • 分布式系列三: 对象序列化

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

    几种序列化机制

    JDK的序列化

    Java默认的序列化要求实现Serializable接口.

    缺点:

    1. 序列化的结果比较大, 占用字节多, 传输效率低
    2. 仅Java实现, 不能跨语言

    WebService

    基于XML格式的传输.

    Json方式

    缺点:

    1. 结果依然较大
    2. 性能低

    二进制传输

    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;
        }
    }
    
    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>
    
  • 相关阅读:
    local_irq_disable和disable_irq的区别
    linux内核IDR机制详解【转】
    飞秋2013设置后无法保存配置问题
    windows 格式化D盘
    query 中 radio选中小技巧
    磁盘碎片整理
    服务器如何选择备案产品类型?
    虚拟主机需要备案吗?
    操作系统自带的截图工具无法保存问题
    CA210彩分仪校准步骤
  • 原文地址:https://www.cnblogs.com/walkinhalo/p/9661424.html
Copyright © 2011-2022 走看看