开发学院,分享开发教程和最新动态
章节列表 什么是ProtobufProtobuf3 定义数据类型Protobuf3 标量值类型Protobuf3 缺省值Protobuf3 枚举Protobuf3 使用其他消息类型Protobuf3 嵌套类型Protobuf3 更新消息类型Protobuf3 未知字段Protobuf3 Any类型Protobuf3 OneofProtobuf3 MapsProtobuf3 包Protobuf3 定义服务Protobuf3 JSON映射Protobuf3 可选项Protobuf3 生成属于自己的类Protobuf 风格指南Protobuf 编码(1)Protobuf 编码(2)Protobuf 编码(3)Protobuf 技术Protocol Buffer C++实例教程: 为什么使用Protocol Buffer?Protocol Buffer C++实例教程: 定义协议格式Protocol Buffer C++实例教程: 编译Protocol BufferProtocol Buffer C++实例教程: Protocol Buffer APIProtocol Buffer C++实例教程: 发送消息Protocol Buffer C++实例教程: 读取消息Protocol Buffer C++实例教程: 扩展Protocol BufferProtocol Buffer C++实例教程: 优化技巧和高级用法Protocol Buffer C#实例教程: 前言Protocol Buffer C#实例教程:定义协议格式Protocol Buffer C#实例教程:编译Protocol Buffer Protocol Buffer C#实例教程:解析和序列化Protocol Buffer Go实例教程:前言Protocol Buffer Go实例教程:定义协议格式Protocol Buffer Go实例教程:编译Protocol BufferProtocol Buffer Go实例教程:读写消息Protocol Buffer JAVA实例教程:前言Protocol Buffer JAVA实例教程:定义协议格式Protocol Buffer JAVA实例教程:编译Protocol BufferProtocol Buffer JAVA实例教程:Protocol Buffer APIProtocol Buffer JAVA实例教程:写消息Protocol Buffer JAVA实例教程:读消息Protocol Buffer JAVA实例教程:扩展Protocol BufferProtocol Buffer Python实例教程:前言Protocol Buffer Python实例教程:定义消息格式Protocol Buffer Python实例教程:编译Protocol BufferProtocol Buffer Python实例教程:Protocol Buffer APIProtocol Buffer Python实例教程:写消息Protocol Buffer Python实例教程:读取MessageProtocol Buffer Python实例教程:扩展Protocol Buffer

Protocol Buffer JAVA实例教程:定义协议格式

  要创建地址簿程序,您需要从. proto文件开始。. proto文件中的定义很简单:为要序列化的每个数据结构添加一条消息,然后为消息中的每个字段指定一个名称和类型。下面是定义好的消息文件,addressbook.proto。

syntax = "proto2";

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;
}

  如您所见,语法类似于C++或java。让我们检查一下文件的每个部分,看看它有什么作用。

  .proto文件以包声明开始,这有助于防止不同项目之间的命名冲突。在java中,包名被用作Java包,除非您已经明确指定了一个Java包,就像我们在这里所做的那样。即使您提供了一个java包,您也应该定义一个普通的包,以避免在Protocol Buffers名字空间和非Java语言中的名字冲突。

  在包声明之后,您可以看到两个特定于Java的选项:java_package和java_outer_classname。java_package指定生成的类应该以什么样的java包名存在。如果没有明确指定,它只是与包声明中给出的包名相匹配,但是这些名称通常不是合适的Java包名(因为它们通常不以域名开头)。java_outer_classname选项定义了应该包含该文件中所有类的类名。如果没有明确给出java_outer_classname,它将通过将文件名转换为camel大小写来生成。例如,默认情况下,“my_proto.proto”将使用“MyProto”作为外部类名。

  接下来,您需要定义消息。消息只是包含一组类型化字段的集合。许多标准的简单数据类型作为字段类型可用,包括bool、int32、float、double和string。您还可以通过使用其他消息类型作为字段类型来为消息添加进一步的结构,在上面的示例中,Person消息包含PhoneNumber消息,而AddressBook消息包含Person消息。您甚至可以定义嵌套在其他消息中的消息类型,如您所见,PhoneNumber类型是在Person中定义的。如果您希望某个字段具有预定义的值列表之一,也可以定义枚举类型,在这里,您希望指定电话号码可以是MOBILE, HOME或WORK之一。

  每个元件识别上的" = 1", " = 2"标记是字段在二进制编码中使用的唯一“标签”。标签号1-15需要比更高的数字少一个字节来编码,因此作为一种优化,您可以决定将那些标签用于常用或重复的元素,而将标签号16和更高的用于不常用的可选元素。重复字段中的每个元素都需要重新编码标签号,因此重复字段是这种优化的特别好的候选者。

  每个字段必须用以下修饰符之一进行注释:

  •   required: 必须为字段提供一个值,否则消息将被视为“uninitialized”。试图构建未初始化的消息将引发RuntimeException。解析未初始化的消息将引发IOException。除此之外,必填字段的行为与可选字段完全一样。

  •   optional: 该字段可以被设置,也可以不被设置。如果未设置可选字段值,则使用默认值。对于简单类型,您可以指定自己的默认值,就像我们在示例中对电话号码类型所做的那样。否则,将使用系统默认值:数字类型为零,字符串为空字符串,布尔值为假。对于嵌入式消息,默认值始终是消息的“default instance”或“prototype”,其中没有设置任何字段。调用访问器来获取未显式设置的optional (或required)字段的值总是返回该字段的默认值。

  •   repeated: 该字段可以重复任何次数(包括零)。重复值的顺序将保留在Protocol Buffer中。将重复字段视为动态大小的数组。

  Required是永久性的。在根据需要标记字段时,您应该非常小心。如果您希望在某个时候停止写入或发送Required字段,将该字段更改为optional 将会有问题,旧的接收者会认为没有该字段的邮件不完整,可能会无意中拒绝或丢弃它们。您应该考虑为您的Protocol Buffer编写特定于应用程序的自定义验证例程。谷歌的一些工程师得出结论,使用Required弊大于利;他们更喜欢只使用optional和repeated。然而,这种观点并不普遍。

  你会找到完整的写作指南。Protocol Buffer 语言指南中的原型文件,包括所有可能的字段类型。但是,别尝试寻找类似于类继承的工具,Protocol Buffer 不会这样做。