java 序列化方式/ protostuff 序列化

1、java原生的序列化

1.1、实现Serializable接口

序列化的时候的一个关键字:transient(临时的)。它声明的变量实行序列化操作的时候不会写入到序列化文件中去。

 

/**
 * Created by Lance on 2018/3/16.
 * 实现Serializable接口
 */
public class Person implements Serializable{

    private String name;
    private Integer age;
    //使用transient关键字修饰的变量不会被序列化
    private transient String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Person() {
    }

    public Person(String name, Integer age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}
/**
 * Created by Lance on 2018/3/16.
 * 把序列化的对象写到文件中去
 * 把文件中的对象读出来打印出来
 */
public class Main {

    public static void main(String[] args) {

        Person person = new Person("小红", 18, "三环");
        try {
            ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("D:\\work\\text4.txt"));
            outputStream.writeObject(person);
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("D:\\work\\text4.txt"));
            Person person1 = (Person) inputStream.readObject();
            System.out.println(person1.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

1.2实现Externalizable接口:

一个类中我们只希望序列化一部分数据,其他数据都使用transient修饰的话显得有点麻烦,这时候我们使用externalizable接口,指定序列化的属性。

 

/**
 * Created by Lance on 2018/3/16.
 * 实现Externalizable接口
 */
public class Member implements Externalizable{

    private String name;
    private Integer age;
    private String address;

    public Member() {
    }

    public Member(String name, Integer age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    @Override
    public String toString() {
        return "Member{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    //必须实现readExternal方法,控制读入什么属性
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        name = (String) in.readObject();
        age = (Integer) in.readObject();
    }

    //必须实现writeExternal方法,控制写出什么属性
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(name);
        out.writeObject(age);
    }
}
/**
 * Created by Lance on 2018/3/16.
 * 把序列化的对象写到文件中去
 * 把文件中的对象读出来打印出来
 */
public class Main {

    public static void main(String[] args) {

        Member member = new Member("小红", 18, "三环");
        try {
            ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("D:\\work\\text4.txt"));
            outputStream.writeObject(member);
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("D:\\work\\text4.txt"));
            Member member1 = (Member) inputStream.readObject();
            System.out.println(member1.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

 

 

 

Externalizable 实例类的唯一特性是可以被写入序列化流中,该类负责保存和恢复实例内容。 若某个要完全控制某一对象及其超类型的流格式和内容,则它要实现 Externalizable 接口的 writeExternal 和 readExternal 方法。这些方法必须显式与超类型进行协调以保存其状态。这些方法将代替定制的 writeObject 和 readObject 方法实现。

writeExternal(ObjectOutput out) 
          该对象可实现 writeExternal 方法来保存其内容,它可以通过调用 DataOutput 的方法来保存其基本值,或调用 ObjectOutput 的 writeObject 方法来保存对象、字符串和数组。

readExternal(ObjectInput in) 
          对象实现 readExternal 方法来恢复其内容,它通过调用 DataInput 的方法来恢复其基础类型,调用 readObject 来恢复对象、字符串和数组。

2、Json序列化

Json序列化一般会使用jackson包,通过ObjectMapper类来进行一些操作,比如将对象转化为byte数组或者将json串转化为对象。现在的大多数公司都将json作为服务器端返回的数据格式。

 

 

3、FastJson序列化

fastjson 是由阿里巴巴开发的一个性能很好的Java 语言实现的 Json解析器和生成器。特点:速度快,测试表明fastjson具有极快的性能,超越任其他的java json parser。功能强大,完全支持java bean、集合、Map、日期、Enum,支持范型和自省。

 

4、ProtoBuff序列化

 

ProtocolBuffer是一种轻便高效的结构化数据存储格式,可以用于结构化数据序列化。适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

优点:跨语言;序列化后数据占用空间比JSON小,JSON有一定的格式,在数据量上还有可以压缩的空间。

缺点:它以二进制的方式存储,无法直接读取编辑,除非你有 .proto 定义,否则无法直接读出 Protobuffer的任何内容。

其与thrift的对比:两者语法类似,都支持版本向后兼容和向前兼容,thrift侧重点是构建跨语言的可伸缩的服务,支持的语言多,同时提供了全套RPC解决方案,可以很方便的直接构建服务,不需要做太多其他的工作。 Protobuffer主要是一种序列化机制,在数据序列化上进行性能比较,Protobuffer相对较好。

引入工具类

<!-- https://mvnrepository.com/artifact/com.dyuproject.protostuff/protostuff-runtime -->
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-runtime</artifactId>
            <version>1.1.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.dyuproject.protostuff/protostuff-core -->
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-core</artifactId>
            <version>1.1.3</version>
        </dependency>

 

引入工具类

package com.flnet.utils.protostuff;

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtobufIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import org.springframework.objenesis.Objenesis;
import org.springframework.objenesis.ObjenesisStd;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * ProtoStuffConfig class
 *
 * @author Lasse
 * @date 2018/8/1
 */
public class ProtoStuffConfig {

    private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>();

    private static Objenesis objenesis = new ObjenesisStd(true);

    private static <T> Schema<T> getSchema(Class<T> cls) {
        Schema<T> schema = (Schema<T>) cachedSchema.get(cls);
        if (schema == null) {
            schema = RuntimeSchema.createFrom(cls);
            if (schema != null) {
                cachedSchema.put(cls, schema);
            }
        }
        return schema;
    }

    public static <T> String serializeToString(T obj) {
        Class<T> cls = (Class<T>) obj.getClass();
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            Schema<T> schema = getSchema(cls);
            return new String(ProtobufIOUtil.toByteArray(obj, schema, buffer), "ISO8859-1");
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        } finally {
            buffer.clear();
        }
    }

    public static <T> T deserializeFromString(String data, Class<T> cls) {
        try {
            T message = (T) objenesis.newInstance(cls);
            Schema<T> schema = getSchema(cls);
            ProtobufIOUtil.mergeFrom(data.getBytes("ISO8859-1"), message, schema);
            return message;
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }


    public static <T> byte[] serializeToByte(T obj) {
        Class<T> cls = (Class<T>) obj.getClass();
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            Schema<T> schema = getSchema(cls);
            return ProtobufIOUtil.toByteArray(obj, schema, buffer);
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        } finally {
            buffer.clear();
        }
    }

    public static <T> T deserializeFromByte(byte[] data, Class<T> cls) {
        try {
            T message = (T) objenesis.newInstance(cls);
            Schema<T> schema = getSchema(cls);
            ProtobufIOUtil.mergeFrom(data, message, schema);
            return message;
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }
}

使用 protostuff 序列化

/**
	 * 用protostuff序列化
	 */
	public void setObjectWithProtostuff() {
		User user = new User(1, "浮生", "123456");
		byte[] bytes = ProtoStuffConfig.serializeToByte(user);
		Message message = new Message(bytes, new MessageProperties());
		System.out.println("sender : " + user.toString());
		amqpTemplate.convertAndSend("mediaDirectExchange","dramaQueueProtoStuffObject", message);
	}

protostuff 接受消息

@RabbitHandler
    @RabbitListener(queues = "dramaQueueProtoStuffObject")
    public void process5(Message hello) {
        UserTest userTest = ProtoStuffConfig.deserializeFromByte(hello.getBody(), UserTest.class);
        System.out.println("Receiver2 : " + userTest.toString());
    }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值