一看就会系列之序列化(Java/avro/protobuf/thrift)入门

目录

 

一、Java原生序列化

二、avro序列化

三、protobuf序列化

四、thrift序列化


一、Java原生序列化

实体类 :

Employee.java

package com.zhuyun.serialize.java;

import java.io.Serializable;

public class Employee implements Serializable
{
   public String name;
   public String address;
   public transient int SSN;
   public int number;
   public void mailCheck()
   {
      System.out.println("Mailing a check to " + name
                           + " " + address);
   }
}

 

序列化,并存储在文件中:

SerializeDemo.java

package com.zhuyun.serialize.java;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;


//序列化
public class SerializeDemo
{
   public static void main(String [] args)
   {
      Employee employee = new Employee();
      employee.name = "Reyan Ali";
      employee.address = "Phokka Kuan, Ambehta Peer";
      employee.SSN = 11122333;
      employee.number = 101;
      try
      {
         FileOutputStream fileOut =
         new FileOutputStream("employee.ser");
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         out.writeObject(employee);
         out.close();
         fileOut.close();
         System.out.printf("Serialized data is saved in employee.ser");
      }catch(IOException i)
      {
          i.printStackTrace();
      }
   }
}

如图,会生成一个文件,保存着实体类Employee序列化后的二进制内容

 

从文件中反序列化成Employee实体类:

DeserializeDemo.java

package com.zhuyun.serialize.java;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class DeserializeDemo
{
   public static void main(String [] args)
   {
      Employee employee = null;
      try
      {
         FileInputStream fileIn = new FileInputStream("employee.ser");
         ObjectInputStream in = new ObjectInputStream(fileIn);
         employee = (Employee) in.readObject();
         in.close();
         fileIn.close();
      }catch(IOException i)
      {
         i.printStackTrace();
         return;
      }catch(ClassNotFoundException c)
      {
         System.out.println("Employee class not found");
         c.printStackTrace();
         return;
      }
      System.out.println("Deserialized Employee...");
      System.out.println("Name: " + employee.name);
      System.out.println("Address: " + employee.address);
      System.out.println("SSN: " + employee.SSN);
      System.out.println("Number: " + employee.number);
    }
}

运行结果如下:

一般来说,Java的序列化性能比较低,在一些通信的开源框架中不会使用Java原生的序列化。

 

二、avro序列化

pom依赖

<dependency>
	  <groupId>org.apache.avro</groupId>
	  <artifactId>avro</artifactId>
	  <version>1.8.2</version>
</dependency>

 

定义一个user schema,格式是avro文件

user.avsc

{"namespace": "com.zhuyun.serialize.java.avro",
 "type": "record",
 "name": "User",
 "fields": [
     {"name": "name", "type": "string"},
     {"name": "favorite_number",  "type": ["int", "null"]},
     {"name": "favorite_color", "type": ["string", "null"]}
 ]
}

下载avro的工具:

http://www.apache.org/dyn/closer.cgi/avro/

 

使用下载的avro工具,根据user.avsc文件来生成一个user.java的文件:

java -jar /path/to/avro-tools-1.9.0.jar compile schema user.avsc .

user.java文件类似如下(注:不要手动修改该类)

 

序列化和反序列化:

AvroDemo.java

package com.zhuyun.serialize.java.avro;

import java.io.File;
import java.io.IOException;

import org.apache.avro.file.DataFileReader;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.specific.SpecificDatumReader;
import org.apache.avro.specific.SpecificDatumWriter;

public class AvroDemo {
	
	public static void main(String[] args) {
		//创建用户
		User user1 = new User();
		user1.setName("Alyssa");
		user1.setFavoriteNumber(256);
		// Leave favorite color null

		// Alternate constructor
		User user2 = new User("Ben", 7, "red");

		// Construct via builder
		User user3 = User.newBuilder()
		             .setName("Charlie")
		             .setFavoriteColor("blue")
		             .setFavoriteNumber(null)
		             .build();
		
		
		System.out.println("user1=" + user1);
		System.out.println("user2=" + user2);
		System.out.println("user3=" + user3);
		
		//序列化并存储到磁盘文件
		try {
			DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class);
			DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter);
			dataFileWriter.create(user1.getSchema(), new File("users.avro"));
			dataFileWriter.append(user1);
			dataFileWriter.append(user2);
			dataFileWriter.append(user3);
			dataFileWriter.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		//从磁盘文件中反序列化
		try {
			DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class);
			DataFileReader<User> dataFileReader = new DataFileReader<User>(new File("users.avro"), userDatumReader);
			User user = null;
			while (dataFileReader.hasNext()) {
			user = dataFileReader.next(user);
			System.out.println("user=" + user);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
}

初始化实体类的方式有好几种,例如setter、构造函数、builder模式等。

序列化后会生成一个文件,保存着实体类user序列化后的二进制内容

执行结果如下:

 

三、protobuf序列化

pom依赖:

<dependency>
	    <groupId>com.google.protobuf</groupId>
	    <artifactId>protobuf-java</artifactId>
	    <version>3.1.0</version>
</dependency>

 

定义一个Student schema,文件格式是.proto,内容如下:

Student.proto

syntax = "proto3";

message Student
{
    int32 number = 1;
    string name = 2;
    int32 sex = 3;
    string hobby = 4;
    string skill = 5;
}

 

下载protobuf的工具:

https://github.com/protocolbuffers/protobuf/releases/

 

使用下载的protobuf工具,根据Student.proto文件来生成一个java文件:

protoc -I=proto的输入目录 --java_out=java类输出目录 proto的输入目录/xxx.proto

生成的java类 类似如下(注:不要手动修改该类)

 

序列化和反序列化:

package com.zhuyun.serialize.java.protobuf;

import com.google.protobuf.InvalidProtocolBufferException;
import com.zhuyun.serialize.java.protobuf.StudentOuterClass.Student;

public class ProtobufDemo {
	public static void main(String[] args) {
		Student.Builder buidler = Student.newBuilder();
        buidler.setName("Frank");
        buidler.setNumber(123456);
        buidler.setHobby("music");
        Student student = buidler.build();
        System.out.println(student.toString());
        
        //序列化
        byte[] array = student.toByteArray();
        //反序列化
        try {
            Student student1 = Student.parseFrom(array);
            System.out.println(student1.toString());
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }   
	}
}

运行结果如下:

 

四、thrift序列化

pom依赖:

<dependency>
      <groupId>org.apache.thrift</groupId>
      <artifactId>libthrift</artifactId>
      <version>0.10.0</version>
</dependency>

 

定义一个Hello schema,文件格式是.thrift,内容如下:

Hello.thrift

namespace java com.zhuyun.serialize.java.thrift
service Hello{
    string helloString(1:string para)
}

 

下载thrift的工具:

http://thrift.apache.org/download

 

使用下载的thrift工具,根据Hello.thrift文件来生成一个java文件:

thrift --gen java Hello.thrift

生成的java类 类似如下(注:不要手动修改该类)

 

接口的实现类如下:

HelloServiceImpl.java

package com.zhuyun.serialize.java.thrift;

import org.apache.thrift.TException;
/**
 * @author infi
 * @date 2017/02/21-下午2:13.
 */
public class HelloServiceImpl implements Hello.Iface {
    public String helloString(String para) throws TException {
        return "result:"+para;
    }
}

 

thrift服务端:

HelloServiceServer.java

package com.zhuyun.serialize.java.thrift;

import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;

/**
 * @author infi
 * @date 2017/02/21-下午2:15.
 */
public class HelloServiceServer {
    /**
     * 启动thrift服务器
     * @param args
     */
    public static void main(String[] args) {
        try {
            System.out.println("服务端开启....");
            TProcessor tprocessor = new Hello.Processor<Hello.Iface>(new HelloServiceImpl());
            // 简单的单线程服务模型
            TServerSocket serverTransport = new TServerSocket(9898);
            TServer.Args tArgs = new TServer.Args(serverTransport);
            tArgs.processor(tprocessor);
            tArgs.protocolFactory(new TBinaryProtocol.Factory());
            TServer server = new TSimpleServer(tArgs);
            server.serve();
            }catch (TTransportException e) {
            e.printStackTrace();
        }
    }
}

thrift客户端:

HelloServiceClient.java

package com.zhuyun.serialize.java.thrift;

import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

/**
 * @author yogo.wang
 * @date 2017/02/21-下午2:35.
 */
public class HelloServiceClient {

    public static void main(String[] args) {
        System.out.println("客户端启动....");
        TTransport transport = null;
        try {
            transport = new TSocket("localhost", 9898, 30000);
            // 协议要和服务端一致
            TProtocol protocol = new TBinaryProtocol(transport);
            Hello.Client client = new Hello.Client(protocol);
            transport.open();
            String result = client.helloString("哈哈");
            System.out.println(result);
        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            if (null != transport) {
                transport.close();
            }
        }
    }
}

运行结果如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值