本文介绍的Protocol Buffer序列化与反序列工具,它的好处是可以将Java对象序列化成“xxx.bin”的二进制字节数据存储在本地,是一种不可读的,体积很小的,传输更快的格式,具体对Google protobuf的介绍,可以看看如下这段话:
Protocol Buffer 和 XML、JSON一样都是结构数据序列化的工具,但它们的数据格式有比较大的区别: 首先,Protocol Buffer 序列化之后得到的数据不是可读的字符串,而是二进制流 其次,XML 和 JSON 格式的数据信息都包含在了序列化之后的数据中,不需要任何其它信息就能还原序列化之后的数据;但使用 Protocol Buffer 需要事先定义数据的格式(.proto 协议文件),还原一个序列化之后的数据需要使用到这个定义好的数据格式 最后,在传输数据量较大的需求场景下,Protocol Buffer 比 XML、JSON 更小(3到10倍)、更快(20到100倍)、使用 & 维护更简单;而且 Protocol Buffer 可以跨平台、跨语音使用。 |
Protocol Buffer可支持的开发语言有:Java, C++, C#, Go, Python, Dart等
构建 Protocol Buffer 消息对象模型:
解释:我们需要先用一个proto文件来定义实体类的模型格式,如addressbook.proto文件
,然后通过Protobuf客户端工具生成对应语言的实体类,例如本案例将会生成一个Addressbook.java类,改java类里面会生成很多方法。
Protobuf 安装:
进入protobuf的github去下载对应版本,下载地址:https://github.com/protocolbuffers/protobuf/releases/tag/v21.2
例如小编下载完windows版本之后,直接解压到电脑系统盘即可,解压之后,进入bin目录会看到一个protoc.exe的执行文件:
1:安装完protobuf之后,我们可以在java项目中加入maven依赖:
<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>${protobuf.version}</version> </dependency> <properties> <protobuf.version>3.2.0</protobuf.version> </properties>
2:定义一个addressbook.proto模型
package protobuf; option java_package = "com.baeldung.protobuf"; option java_outer_classname = "AddressBookProtos"; message Person { required string name = 1; required int32 id = 2; optional string email = 3; repeated string numbers = 4; } message AddressBook { repeated Person people = 1; }
java_package:文件生成的java包名
java_outer_classname:生成的java类名
required:实例化java类时必须要设置的属性,setXXX,在protobuf 3.0之后,不再支持这个属性
optional:可选属性,可以set设置,也可以不设置该属性的值
repeated:表示一个List集合或者Array数组的属性
3:根据proto模型文件生成对应的java类,在上图中的bin目录进入console控制台,输入如下Protocol Buffer命令:
protoc -I=. --java_out=. addressbook.proto
输入上方protobuf命令之后,就会自动生成一个AddressBookProtos.java的类,里面会包含各种方法,以及Protocol Buffer序列化反序列的方法。
4:创建一个Person对象(小试牛刀):
String email = "j@baeldung.com"; int id = new Random().nextInt(); String name = "Michael Program"; String number = "01234567890"; AddressBookProtos.Person person = AddressBookProtos.Person.newBuilder() .setId(id) .setName(name) .setEmail(email) .addNumbers(number) .build(); //判断获取的值 assertEquals(person.getEmail(), email); assertEquals(person.getId(), id); assertEquals(person.getName(), name); assertEquals(person.getNumbers(0), number);
5:Protobuf序列化,就是将Person实体类数据写入到xxx.bin二进制文件里面保持起来,protobuf生成的java类里面自带类write方法:
AddressBookProtos.AddressBook addressBook = AddressBookProtos.AddressBook.newBuilder().addPeople(person).build(); FileOutputStream fos = new FileOutputStream(filePath); addressBook.writeTo(fos);
6:Protobuf反序列化xxx.bin文件里面的Person实体类数据:
//获取指定路径下的bin文件序列化内容 AddressBookProtos.AddressBook deserialized = AddressBookProtos.AddressBook.newBuilder() .mergeFrom(new FileInputStream(filePath)).build(); assertEquals(deserialized.getPeople(0).getEmail(), email); assertEquals(deserialized.getPeople(0).getId(), id); assertEquals(deserialized.getPeople(0).getName(), name); assertEquals(deserialized.getPeople(0).getNumbers(0), number);
总结:
由于Protocol Buffer序列化反序列化之后的数据体积比较小,所以比xml或者json更适合数据的传输,速度也更快。