protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。
Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。
你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。
1、使用prorobuf
1.1创建 .proto 文件,定义数据结构
message xxx {
// 字段规则:required -> 字段只能也必须出现 1 次
// 字段规则:optional -> 字段可出现 0 次或1次
// 字段规则:repeated -> 字段可出现任意多次(包括 0)
// 类型:int32、int64、sint32、sint64、string、32-bit ....
// 字段编号:0 ~ 536870911(除去 19000 到 19999 之间的数字)
字段规则 类型 名称 = 字段编号;
}
- required: 格式良好的 message 必须包含该字段一次。
- optional: 格式良好的 message 可以包含该字段零次或一次(不超过一次)。
- repeated: 该字段可以在格式良好的消息中重复任意多次(包括零)。其中重复值的顺序会被保留。
message 定义中的每个字段都有唯一编号。这些数字以 message 二进制格式 标识你的字段,并且一旦你的 message 被使用,这些编号就无法再更改。请注意,1 到 15 范围内的字段编号需要一个字节进行编码,编码结果将同时包含编号和类型(你可以在 Protocol Buffer 编码 中找到更多相关信息)。16 到 2047 范围内的字段编号占用两个字节。因此,你应该为非常频繁出现的 message 元素保留字段编号 1 到 15。请记住为将来可能添加的常用元素预留出一些空间。 你可以指定的最小字段数为 1,最大字段数为 229 - 1 或 536,870,911。你也不能使用 19000 到 19999 范围内的数字(FieldDescriptor::kFirstReservedNumber
到 FieldDescriptor::kLastReservedNumber
),因为它们是为 Protocol Buffers 的实现保留的 - 如果你使用这些保留数字之一.
例子:test.proto
//指定protobuf语法版本
syntax = "proto2";
//包名
option java_package = "com.lhc.protobuf";
//源文件类名 即生成AddressBookProtos.java
option java_outer_classname = "AddressBookProtos";
// class Person
message Person {
//required 必须设置(不能为null)
required string name = 1;
//int32 对应java中的int
required int32 id = 2;
//optional 可以为空
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 重复的 (集合)
repeated PhoneNumber phones = 4;
}
message AddressBook {
repeated Person people = 1;
}
注意:Repeated
proto2 中声明为具有特殊的 [packed = true] 选项的 repeated 字段。packed repeated 和 repeated 在编码方式上会有所不同。没有包含任何元素的 packed repeated 字段不会出现在编码消息中。否则(包含有元素),该字段的所有元素都被打包成一个键值对,其中类型(wire type)为 2(length-delimited)。每个元素的编码方式与正常情况相同,只是前面没有键。(意思添加这个选项之后 相同类型的公用一个键,相当于减少了键值)
例如:
现在假设你构造一个 Test4,为重复的字段 d 分别赋值为 3、270 和 86942。那么对应的编码将是:
22 // key (或称 tag,字段编码 4, wire type 2)
06 // payload 长度 (即后面需要读取的所有值的长度6 bytes)
03 // first element (varint 3)
8E 02 // second element (varint 270)
9E A7 05 // third element (varint 86942)
只有原始数字类型(使用 Varint,32-bit 或 64-bit)的 repeated 字段才能声明为 “packed”。
2、生成proto java文件
2.1 安装编译环境
下载地址:https://github.com/google/protobuf/releases 选择tag选择相应的版本。
1、根据使用的protobuf 版本下载相应的ZIP 包。下载:protoc-3.6.0-win32.zip(protoc-2.5.0-win32.zip) 和 protobuf-java-3.6.0.zip(protobuf-2.5.0.zip)
2、将protoc-3.1.0-win32中的protoc.exe拷贝到c:\windows\system32中
3、 将proto.exe文件拷贝到解压后的protobuf-3.1.0\src目录中
4、protobuf-3.1.0\java 目录下执行maven package命令编辑该包 生成protobuf-java-3.1.0.jar文件(这一步相当于安装了,位于protobuf-3.1.0\java\core\target目录中)。编译成功如下图:
2.2 编译生成JAVA文件
1、从cmd命令窗口进入XXX/protoc-3.6.0-win32\bin 目录
使用命令:protoc -I=源地址 --java_out=目标地址 源地址/xxx.proto
注意:-I选项主要用于指定待编译的.proto消息定义文件所在的目录,即可能出现的包含文件的路径,该选项可以被同时指定多个,此处指定的路径不能为空,如果是当前目录直接使用.即可,如果是子目录则使用子目录的相对路径
如果把 文件拷贝到XXX/protoc-3.6.0-win32\bin 这个目录下 使用如下命令:
protoc --java_out=. xxx.proto (注意等号后面的点 后面以后空格)
参考文件:
https://www.jianshu.com/p/6f68fb2c7d19
https://www.jianshu.com/p/82ff31c6adc6