目录
一、Java原生序列化
二、avro序列化
三、protobuf序列化
四、thrift序列化
实体类 :
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原生的序列化。
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序列化后的二进制内容
执行结果如下:
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(); } } }运行结果如下:
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(); } } } }运行结果如下: