Netty学习——Google Protobuf的初步了解

mitesi 2019-12-02

学习参考的官网: https://developers.google.com/protocol-buffers/docs/javatutorial   

简单指南详解:这个文档写的简直是太详细了。

本篇从下面三个步骤进行介绍:

详细内容,我就不做过多解释,自行查阅官方文档,在这只是记录,我觉得比较重要的东西,能够帮助我更好的理解。


I.Define message formats in a .proto file.    

syntax = "proto2";

package tutorial; //包名

option java_package = "com.example.tutorial";  //针对于java的包名
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];  // optional类型 和定义默认值
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;  //repeated类型,其实就相当于java的ArrayList,用来
}

其他需要注意的点:

1.对于前两个字段java_package  和 package ,就是说,可以不写java_package,会默认 调用package ,写了java_package,java就会识别这个,但是就算写了java_package,也要package ,是为了其他语言能够有包名能够使用

Netty学习——Google Protobuf的初步了解

2.这个数字,=1, =2 ,不是顺序,或者是赋值,只是每一个字段在Proto文件中,都会有一个唯一数字标识符

Netty学习——Google Protobuf的初步了解

3.对于以下的三种类型 required,optional,repeated  官方推荐,尽量不是用required,因为弊大于利。

Netty学习——Google Protobuf的初步了解


II. Use the protocol buffer compiler.

需要注意的地方:

使用PB编译器生成出的对象是不可变的,需要使用构建器的方法连模式(set.set.set )一个一个的去设置值,然后再需要最后使用build方法去完成整个对象的创建,如下介绍

每一次set完之后的返回结果,都是另一个构建器,就是为了能够在一行代码上,完成对象的构建

Netty学习——Google Protobuf的初步了解

通过构建器的方法连模式,完成一个对象的创建和设置值的标准写法:如下

Person john =
  Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("")
    .addPhones(
      Person.PhoneNumber.newBuilder()
        .setNumber("555-4321")
        .setType(Person.PhoneType.HOME))
    .build();

Message除了自定义的属性之外,还提供的有几个默认的方法,让你能够检查和操作整个消息

isInitialized()://检查是否所有的必备字段,都已经被设置值

toString(): //返回一个人类可读的字符形式,通常用于调试

mergeFrom()://(只有构建器才有)将另一个消息的内容,合并到当前消息当中并且覆盖之前的标量字段,合并复核的字段和重复的阻断,完成对象的合并

clear()://(只有构建器才有) 恢复到原来属性都为空的这个状态

Netty学习——Google Protobuf的初步了解

解析和序列化这些消息

byte[] toByteArray(); //将消息序列化,并返回了包含原生字节的一个字节数组,就是把消息本身转换成字节数组

static Person parseFrom(byte[] data);//从给定的字节数组当中解析这条消息,将字节数组的内容转换成对象

void writeTo(OutputStream output);//将消息序列化,并输出到一个输出流当中,

static Person parseFrom(InputStream input); //接着读取输入流中的消息并进行解析

注意:不能通过继承的方式,给这个对象添加更多的行为。

如果想要给这个message对象赋予响应的方法,可以借助使用多个message合并的方式来实现功能而并不是通过继承的方式

Netty学习——Google Protobuf的初步了解 


III. Use the Java protocol buffer API to write and read messages.

Writer a Message 

import com.example.tutorial.AddressBookProtos.AddressBook;
import com.example.tutorial.AddressBookProtos.Person;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintStream;

class AddPerson {
  // This function fills in a Person message based on user input.
  static Person PromptForAddress(BufferedReader stdin,
                                 PrintStream stdout) throws IOException {
    Person.Builder person = Person.newBuilder();

    stdout.print("Enter person ID: ");
    person.setId(Integer.valueOf(stdin.readLine()));

    stdout.print("Enter name: ");
    person.setName(stdin.readLine());

    stdout.print("Enter email address (blank for none): ");
    String email = stdin.readLine();
    if (email.length() > 0) {
      person.setEmail(email);
    }

    while (true) {
      stdout.print("Enter a phone number (or leave blank to finish): ");
      String number = stdin.readLine();
      if (number.length() == 0) {
        break;
      }

      Person.PhoneNumber.Builder phoneNumber =
        Person.PhoneNumber.newBuilder().setNumber(number);

      stdout.print("Is this a mobile, home, or work phone? ");
      String type = stdin.readLine();
      if (type.equals("mobile")) {
        phoneNumber.setType(Person.PhoneType.MOBILE);
      } else if (type.equals("home")) {
        phoneNumber.setType(Person.PhoneType.HOME);
      } else if (type.equals("work")) {
        phoneNumber.setType(Person.PhoneType.WORK);
      } else {
        stdout.println("Unknown phone type.  Using default.");
      }

      person.addPhones(phoneNumber);
    }

    return person.build();
  }

  // Main function:  Reads the entire address book from a file,
  //   adds one person based on user input, then writes it back out to the same
  //   file.
  public static void main(String[] args) throws Exception {
    if (args.length != 1) {
      System.err.println("Usage:  AddPerson ADDRESS_BOOK_FILE");
      System.exit(-1);
    }

    AddressBook.Builder addressBook = AddressBook.newBuilder();

    // Read the existing address book.
    try {
      addressBook.mergeFrom(new FileInputStream(args[0]));
    } catch (FileNotFoundException e) {
      System.out.println(args[0] + ": File not found.  Creating a new file.");
    }

    // Add an address.
    addressBook.addPerson(
      PromptForAddress(new BufferedReader(new InputStreamReader(System.in)),
                       System.out));

    // Write the new address book back to disk.
    FileOutputStream output = new FileOutputStream(args[0]);
    addressBook.build().writeTo(output);
    output.close();
  }
}

Reader a Message

import com.example.tutorial.AddressBookProtos.AddressBook;
import com.example.tutorial.AddressBookProtos.Person;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintStream;

class ListPeople {
  // Iterates though all people in the AddressBook and prints info about them.
  static void Print(AddressBook addressBook) {
    for (Person person: addressBook.getPeopleList()) {
      System.out.println("Person ID: " + person.getId());
      System.out.println("  Name: " + person.getName());
      if (person.hasEmail()) {
        System.out.println("  E-mail address: " + person.getEmail());
      }

      for (Person.PhoneNumber phoneNumber : person.getPhonesList()) {
        switch (phoneNumber.getType()) {
          case MOBILE:
            System.out.print("  Mobile phone #: ");
            break;
          case HOME:
            System.out.print("  Home phone #: ");
            break;
          case WORK:
            System.out.print("  Work phone #: ");
            break;
        }
        System.out.println(phoneNumber.getNumber());
      }
    }
  }

  // Main function:  Reads the entire address book from a file and prints all
  //   the information inside.
  public static void main(String[] args) throws Exception {
    if (args.length != 1) {
      System.err.println("Usage:  ListPeople ADDRESS_BOOK_FILE");
      System.exit(-1);
    }

    // Read the existing address book.
    AddressBook addressBook =
      AddressBook.parseFrom(new FileInputStream(args[0]));

    Print(addressBook);
  }
}

相关推荐