零 版本
Protocol Buf 版本 : 3.10.0
1 Protocol Buf 简介
Protocol Buf 是谷歌出品的一种序列化通讯协议,以高效和跨平台著称。同时理解起来也很晦涩,且中文文档不齐全,不同版本的协议之间兼容性较差。本文从应用的角度聊一下如何在 java 项目中使用该协议。
一 protoc
1 使用思路
首先需要理解,使用 Protocol Buf 的流程是:
[1] 编写 proto 文件
[2] 编译 proto 文件成 java 类
[3] 在 java 项目中以 Builder 方式调用类的构造器
2 编译
首先需要下载相应操作系统平台的解析工具 github[https://github.com/protocolbu…]
在 Win10 上,cmd 执行:
d:\\protoc --java_out=d:\\Message.proto
上述例子中 protoc.exe 被放置在 d 盘下,proto 文件名称叫 Message.proto,也放在 d 盘下。
Linux 和 MacOs 下的命令和 Win10 差不多:
./protoc --java_out=./Message.proto
编译结束后会在指定路径下出现一个 .java 文件,具体路径在 proto 中配置。
二 proto 编写
// 指定协议
syntax = "proto3";
// 指定包名
package cn.mikylin.proto3.test;
// 指定 java 包路径
option java_package = "cn.mikylin.proto3";
// 指定 java class 名称,不可以与 message 名称重复
option java_outer_classname = "MessageTest";
// 引入谷歌编写的 any.proto;any 可以包装任意类型的数据
// 需要到 github 上把 any.proto 下载到和当前 proto 同一个目录下
// import "google/protobuf/any.proto";
/*
message 内是 protobuf 的消息主体部分,可以简单理解为一个 java bean。修饰词:singular - 可以不存在 (非必填唯一项),默认修饰词,无需填写 (填写则会报错)
repeated - 可以不存在或多次 (非必填可多项),默认值空
reserved - 保留字段,不被使用
数据类型:int64 / unit64 - 对应 java 的 long,默认 0
int32 / unit32 - 对应 java 的 int,默认 0
string - 对应 java 的 string,默认空字符串
float - 对应 java 的 float,默认 0
double - 对应 java 的 double,默认 0
bool - 对应 java 的 boolean,默认 false
bytes - 对应 java 的 byteString
*/
message Test {
int64 test_1 = 1;
string test_2 = 2;
int32 test_3 = 3;
repeated int64 test_4 = 4;
// message 内部可以定义其它 message
// 需要注意的是,message 里的参数名和外面的不能重复
message Test_Inner_Message {
int64 test_inner_1 = 1;
string test_inner_2 = 2;
repeated int32 test_inner_3 = 3;
}
Test_Inner_Message test_5 = 5;
// 枚举是一种自定义的有限集合的类型
enum TEST_ENUM {
TEST_ENUM_0 = 0;
TEST_ENUM_1 = 1;
TEST_ENUM_2 = 2;
}
repeated TEST_ENUM test_6 = 6;
reserved "foo", "bar";
// string foo = 6; // 此处会报错,因为 foo 已经是保留字段了
// oneof 修饰的数据,当其中一个存在值的时候,另一个置空
oneof Test_Oneof {
string test_oneof_1 = 7;
int32 test_oneof_2 = 8;
}
// Any 类型的参数必须
// google.protobuf.Any data = 8;
}
java 应用
public static void main(String[] args) {
MessageTest.Test build = MessageTest.Test
.newBuilder()
.setTest1(11L)
.setTest2("2333")
.setTest5(
MessageTest
.Test
.Test_Inner_Message
.newBuilder()
.setTestInner2("2333333")
.build())
.build();
System.out.println(build.getTest1());
}