Protobuf是一个灵活的、高效的用于序列化数据的协议。相比较XML和JSON格式,protobuf更小、更快、更便捷。google protobuf是跨语言的,并且自带了一个编译器(protoc),只需要用它进行编译,可以编译成Java、python、C++、C#、Go等代码,然后就可以直接使用,不需要再写其他代码,自带有解析的代码。本篇文章将简要的介绍Java程序员如何使用Protobuf。
工欲善其事,必先利其器。在使用Protobuf进行开发前,需要安装Protobuf的编译器。Protobuf编译器能够将.proto描述文件解析为特定特定语言中的类。我们可以通过两种途径获取代码,一种是通过google protobuf github,另一种比较简单的做法是从Protobuf的发行版页面中下载合适版本的预构建文件,这里我们下载protobuf-java-3.3.0.tar.gz
下载完成后,进行解压安装
tar -zxvf protobuf-java-3.3.0.tar.gz cd protobuf-java-3.3.0 ./configure #进行环境监测,并生成makefile文件 make # 编译 make install # 安装这里有两点需要注意: 1. 如果是通过github下载源码编译安装,则需要先执行./autogen.sh,这一步主要用来联网获取GoogleMock数据,并生成对应的configure脚本。脚本生成完成后,编译安装步骤和下载release包时一样; 2. 在./configure进行环境检测时,可以通过–prefix=/user/local来指定安装路径
安装完成后,可以通过–version命令来检测是否安装成功
$ protoc --version libprotoc 3.3.0我们以protobuf官网java入门教程中的例子为例,编写一个addressbook.proto
package tutorial; option java_package = "com.example.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 phones = 4; } message AddressBook{ repeated Person people = 1; }需要进行说明的几点: 1. package声明是为了防止不同项目中的命名冲突。option java_package的意思是说,如果该.proto被编译为Java类型的文件,则包名使用java_package制定的路径,否则使用默认路径 2. option java_outer_classname用来声明包含.proto中所有类的类的名字,也即最外层类的名字。如果不指定的话,默认使用.proto文件名的驼峰形式。例如my_proto.proto编译生成的类文件名为MyProto 3. message用来代表一个类,required用来代表该字段是必须的,缺少该字段将会导致解析异常;option代表可选的,可有可无;repeated代表数组,意味着可以多次出现。
关于Protobuf语法的更多介绍,猛戳这里
使用前面安装好的protoc工具编译addressbook.proto,命令如下:
protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/addressbook.protoSRC_DIR用来指定源码位置,如果不指定的话,默认为当前目录,DST_DIR用来制定输出目录,如果不指定的话,默认为当前位置,–java_out用来指定生成的为java类;如果要生成C++类,则通过–cpp_out来指定。
由于我的当前工作目录已经和addressbook.proto在同一级,因此我不需要指定SRC_DIR,运行命令:
protoc --java_out=./ ./addressbook.proto如果运行一切顺利,会在当前目录中生成com.example.tutorial/AddressBookProtos.java,这个类中包含属性的getter和setter方法,用build模式进行构造。
使用build模式构建对象以后,进行序列化和反序列化的工作就变的很简单了,我们可以通过调用toByteArray方法,将对象转换为字节数组;可以通过parseFrom方法,将字节数组转换为Java对象。
这里只是一个简单的介绍,更多Protobuf对象的方法,请戳这里