一、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();
}
}
}
}