一、介紹
Google提供一個具有高效的協議數據交換格式工具庫(類似Json),但相比於Json,Protobuf有更高的轉化效率,時間效率和空間效率都是JSON的3-5倍。google 提供了三種語言的實現:java、c++ 和 python,每一種實現都包含了相應語言的編譯器以及庫文件。
二、特點
Xml、Json是目前常用的數據交換格式,它們直接使用字段名稱維護序列化后類實例中字段與數據之間的映射關系,一般用字符串的形式保存在序列化后的字節流中。消息和消息的定義相對獨立,可讀性較好。但序列化后的數據字節很大,序列化和反序列化的時間較長,數據傳輸效率不高。
Protobuf和Xml、Json序列化的方式不同,采用了二進制字節的序列化方式,用字段索引和字段類型通過算法計算得到字段之前的關系映射,從而達到更高的時間效率和空間效率,特別適合對數據大小和傳輸速率比較敏感的場合使用。
三、結構
proto文件定義了協議數據中的實體結構(message ,field)。
舉例如下:
//要生成的類Person
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
(1)關鍵字message: 代表了實體結構,由多個消息字段(field)組成。
Message中定義的全部屬性在class中全部為private的。
Message的嵌套使用可以嵌套定義,也可以采用先定義再使用的方式。
(2)消息字段field: 即屬性,包括字段規則+數據類型+字段名+屬性順序號+[默認值]。
-
數據類型:常見的原子類型都支持

-
字段規則:
- required:對於required的字段而言,必須初始化字段,否則會拋異常
- optional:可選字段,可以不必初始化。如果沒初始化,那么將賦予該字段編號一個默認值。int或者char數據類型默認為0,string默認為"",bool默認為false,嵌套message默認為構造,枚舉則為第一個。
- repeated:數據可以重復(相當於java 中的Array或List)
-
字段唯一標識:序列化和反序列化將會使用到。比如上面的=1; =2;
-
默認值:在定義消息字段時可以給出默認值。比如 [default = HOME]
四、選擇版本
syntax 聲明可以選擇protobuf的編譯器版本(v2和v3)
- syntax="proto2":選擇2版本,各個字段必須明確標注編號以確定序列化后二進制數據字段的位置
- syntax="proto3":選擇3版本,沒有強制使用字段編號,proto3 已舍棄 required 字段,optional 字段也無法顯示使用
五、Intellij IDEA中使用Protobuf
1、下載個protoc.exe
- 官網下載地址:http://code.google.com/p/protobuf/downloads/list
- protoc的源碼和各個系統的預編譯包:https://github.com/protocolbuffers/protobuf/releases
在里面下載個protobuf-java-3.7.1.zip,解壓后bin里面有protoc.exe,下載完以后放到項目的resource\proto下。
2、編輯個.proto文件
在proto文件下創建一個AddressBook.proto。用的是proto2版本
里面的結構就是 AddressBook下有很多個Person。
每個Person必須有一個name、必須有一個id、可選有email、很多個PhoneNumber。
每個PhoneNumber必須有一個number、可選PhoneType。
PhoneType取值必為0或1或2

寫的內容舉例如下:
syntax = "proto2";
//生成的類會放在protoc.exe同目錄下的tutorial
//如果.proto文件中寫了java_package,就以java_package為准。
package beans;
//生成的類會放在protoc.exe同目錄下的com.proto.tutorial下
//option java_package = "com.proto.tutorial";
//最終成的類名
//option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2; .
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
package tutorial;
option java_package = "com.proto.tutorial";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2; // Unique ID number for this person.
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
}
3、將.proto文件轉成Java類
控制台中執行protoc命令,依次將.proto文件轉成Java類
protoc.exe -I=F:/workspace/proto-test/src/main/resources/proto --java_out=F:/workspace/proto-test/src/main/java/beans F:/workspace/proto-test/src/main/res
ources/proto/AddressBook.proto
protoc.exe -I=(proto文件所在絕對路徑,不包括proto文件本身) --java_out=(文件輸出目錄) (proto文件所在絕對路徑,包括proto文件名)
4、相關包
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.7.1</version>
</dependency>
<dependency>
<groupId>com.googlecode.protobuf-java-format</groupId>
<artifactId>protobuf-java-format</artifactId>
<version>1.2</version>
</dependency>
5、.proto文件語法高亮顯示
需要安裝Protobuf Support插件,
依次點擊Intellij中的“File”-->"Settings"-->"Plugins"-->"Browse repositories",
輸入Protobuf,點擊install
6、具體使用舉例
AddressBookProtos.AddressBook .Builder addressBook= AddressBookProtos.AddressBook .newBuilder();
AddressBookProtos.Person .Builder person= AddressBookProtos.Person .newBuilder();
person.setName("Mike");
addressBook.setPerson(person);
