ProtoBuf 全称 protocol buffers,是 google 开源的一个平台无关、语言无关的序列化框架。
官网点击这里 protobuf 官网
文本通过一个简单的案例介绍 protobuf 的简单使用。
创建一个 maven 项目,在 resources
下创建一个目录 proto
(可自己更改),然后在该目录下创建一个 addressbook.proto
文件。
syntax = "proto3";
package tutorial;
option java_package = "protobuf.demo.tutorial";
option java_outer_classname = "AddressBookProto";
message Person{
int32 id = 1;
string name = 2;
string email = 3 ;
enum PhoneType{
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber{
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
}
message AddressBook{
string bookName = 1;
repeated Person people = 2;
}
syntax 定义 .proto
文件使用的是 proto3 的语法。proto2 和 proto3 的语法区别可以去官网查看。
package 指的是该 .proto
文件里定义的类的包路径。
option java_package指的最终生成的 java 类所在的包名。
option java_outer_classname指的是最终生成的 java 类的名称。
message指的定义的消息类。
enum 定义枚举类。
repeated 指明该字段可以重复添加,在 java 看来该字段是一个 list 集合。
生成 java 类的方式有很多种,这里用列举两种方式。
编写 maven pom 文件,新增如下内容。
<dependencies>
<dependency>
<groupId>io.grpcgroupId>
<artifactId>grpc-allartifactId>
<version>1.30.1version>
dependency>
dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.mavengroupId>
<artifactId>os-maven-pluginartifactId>
<version>1.6.2version>
extension>
extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.pluginsgroupId>
<artifactId>protobuf-maven-pluginartifactId>
<version>0.5.0version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.0.0-beta-4:exe:${os.detected.classifier}
protocArtifact>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:0.15.0:exe:${os.detected.classifier}pluginArtifact>
<pluginId>grpcpluginId>
<protoSourceRoot>src/main/resources/protoprotoSourceRoot>
configuration>
<executions>
<execution>
<goals>
<goal>compilegoal>
<goal>compile-customgoal>
goals>
execution>
executions>
plugin>
plugins>
build>
引入依赖之后,运行 maven 插件。
运行结束之后在 target
目录下可以看到生成的 java 文件。
去官网下载最新的编译工具,传送门点这里。根据自己的操作系统下载。然后运行如下命令:
protoc -I=./src/main/resources/proto/ --java_out=./src/main/java ./src/main/resources/proto/addressbook.proto
-I 指.proto
文件所在目录,**–java_out **指生成的 java 文件所在的目录,后面紧跟.proto
文件。这样生成的文件如下图:
main 方法如下:
public static void main(String[] args) throws IOException {
File file = new File("address_book.txt");
if (!file.exists() && file.createNewFile()) {
System.out.println("创建了一个新的通讯录" + file.getName());
}
System.out.println("开始新增人员信息");
writeAddressBook(file);
System.out.println("--------------");
System.out.println("开始读取人员信息");
readAddressBook(file);
System.out.println("--------------");
}
生成一个文件,然后写入一个人员信息,再从文件中读取出来。
private static void writeAddressBook(File file) throws IOException {
FileOutputStream outputStream = new FileOutputStream(file);
// 创建一个手机号码
AddressBookProto.Person.PhoneNumber.Builder builder = AddressBookProto.Person.PhoneNumber.newBuilder();
AddressBookProto.Person.PhoneNumber phoneNumber1 = builder
.setNumber("17500001111")
.setType(AddressBookProto.Person.PhoneType.MOBILE)
.build();
builder.clear();
AddressBookProto.Person.PhoneNumber phoneNumber2 = builder
.setNumber("18900002222")
.setType(AddressBookProto.Person.PhoneType.WORK)
.build();
// 创建一个人 韩信
AddressBookProto.Person hanXin = AddressBookProto.Person.newBuilder()
.setId(1)
.setName("韩信")
.setEmail("[email protected]")
.addPhones(phoneNumber1)
.addPhones(phoneNumber2)
.build();
System.out.println("新增通讯录人员信息成功");
// 将 七七这个人的信息添加到通讯录
AddressBookProto.AddressBook addressBook = AddressBookProto.AddressBook.newBuilder()
.setBookName("七七的通讯录")
.addPeople(hanXin)
.build();
// 持久化
outputStream.write(addressBook.toByteArray());
outputStream.close();
}
private static void readAddressBook(File file) throws IOException {
FileInputStream inputStream = new FileInputStream(file);
AddressBookProto.AddressBook addressBook = AddressBookProto.AddressBook.parseFrom(inputStream);
System.out.println(addressBook.getBookName() + ":");
for (AddressBookProto.Person person : addressBook.getPeopleList()) {
System.out.printf("编号:%d\t姓名:%s\n", person.getId(), person.getName());
List<AddressBookProto.Person.PhoneNumber> phonesList = person.getPhonesList();
System.out.printf("\t%s\t%s\n", "号码类型", "号码");
for (AddressBookProto.Person.PhoneNumber phoneNumber : phonesList) {
System.out.printf("\t%s\t%s\n", phoneNumber.getType(), phoneNumber.getNumber());
}
}
}
运行 main 方法,结果如下:
开始新增人员信息
新增通讯录人员信息成功
--------------
开始读取人员信息
七七的通讯录:
编号:1 姓名:韩信
号码类型 号码
MOBILE 17500001111
WORK 18900002222
--------------
结果可以正常写入并读取出来,查看生成的address_book.txt
文件,内容如下:
七七的通讯录<韩信[email protected]"
17500001111"
18900002222