Въведение в Google Protocol Buffer

1. Общ преглед

В тази статия ще разгледаме буфера на Google Protocol (protobuf) - добре познат език-агностичен формат на двоични данни. Можем да дефинираме файл с протокол и след това, използвайки този протокол, можем да генерираме код на езици като Java, C ++, C #, Go или Python.

Това е уводна статия към самия формат; ако искате да видите как да използвате формата с уеб приложение Spring, разгледайте тази статия.

2. Определяне на зависимостите на Maven

За да използваме буфери на протоколи е Java, трябва да добавим зависимост на Maven към protobuf-java:

 com.google.protobuf protobuf-java ${protobuf.version}   3.2.0 

3. Дефиниране на протокол

Нека започнем с пример. Можем да определим много прост протокол във формат protobuf:

message Person { required string name = 1; }

Това е протокол от обикновено съобщение от тип Person , което има само едно задължително поле - име, което има тип низ .

Нека разгледаме по-сложния пример за дефиниране на протокол. Да кажем, че трябва да съхраняваме подробности за човека във формат protobuf:

пакет protobuf;

package protobuf; option java_package = "com.baeldung.protobuf"; option java_outer_classname = "AddressBookProtos"; message Person { required string name = 1; required int32 id = 2; optional string email = 3; repeated string numbers = 4; } message AddressBook { repeated Person people = 1; }

Нашият протокол се състои от два вида данни: Личност и Адресна книга. След генериране на кода (повече за това в следващия раздел), тези класове ще бъдат вътрешните класове в класа AddressBookProtos .

Когато искаме да дефинираме поле, което се изисква - което означава, че създаването на обект без такова поле ще доведе до изключение , трябва да използваме задължителна ключова дума.

Създаването на поле с незадължителната ключова дума означава, че това поле не трябва да се задава. В повтори дума е тип масив с различен размер.

Всички полета се индексират - полето, означено с номер 1, ще бъде запазено като първо поле в двоичен файл. Полето, отбелязано с 2, ще бъде запазено следващо и т.н. Това ни дава по-добър контрол върху това как са разположени полетата в паметта.

4. Генериране на Java код от файл Protobuf

След като дефинираме файл, можем да генерираме код от него.

Първо, трябва да инсталираме protobuf на нашата машина. След като направим това, можем да генерираме код, като изпълним командата protoc :

protoc -I=. --java_out=. addressbook.proto

Командата protoc ще генерира изходен файл на Java от нашия файл addressbook.proto . Опцията -I указва директория, в която се намира прото файл. В Java, навън се задава директорията, където ще бъде създаден генерирания клас.

Генерираният клас ще има сетери, гетери, конструктори и конструктори за нашите дефинирани съобщения. Той също така ще има някои помощни методи за запазване на протобуф файлове и десериализиране от бинарен формат в Java клас.

5. Създаване на екземпляр от съобщения, дефинирани от Protobuf

Можем лесно да използваме генериран код за създаване на Java екземпляр на клас Person :

String email = "[email protected]"; int id = new Random().nextInt(); String name = "Michael Program"; String number = "01234567890"; AddressBookProtos.Person person = AddressBookProtos.Person.newBuilder() .setId(id) .setName(name) .setEmail(email) .addNumbers(number) .build(); assertEquals(person.getEmail(), email); assertEquals(person.getId(), id); assertEquals(person.getName(), name); assertEquals(person.getNumbers(0), number);

Можем да създадем плавен конструктор, като използваме метод newBuilder () за желания тип съобщение. След като настроим всички задължителни полета, можем да извикаме метод build () , за да създадем екземпляр на клас Person .

6. Сериализиране и десериализиране на Protobuf

След като създадем екземпляр от нашия клас Person , искаме да го запазим на диск в двоичен формат, който е съвместим със създаден протокол. Да кажем, че искаме да създадем екземпляр на класа AddressBook и да добавим един човек към този обект.

След това искаме да запазим този файл на диск - има метод за писане writeTo () в автоматично генериран код, който можем да използваме:

AddressBookProtos.AddressBook addressBook = AddressBookProtos.AddressBook.newBuilder().addPeople(person).build(); FileOutputStream fos = new FileOutputStream(filePath); addressBook.writeTo(fos);

След изпълнението на този метод, нашият обект ще бъде сериализиран в двоичен формат и записан на диск. За да заредим тези данни от диск и да ги десериализираме обратно към обекта AddressBook, можем да използваме метода mergeFrom () :

AddressBookProtos.AddressBook deserialized = AddressBookProtos.AddressBook.newBuilder() .mergeFrom(new FileInputStream(filePath)).build(); assertEquals(deserialized.getPeople(0).getEmail(), email); assertEquals(deserialized.getPeople(0).getId(), id); assertEquals(deserialized.getPeople(0).getName(), name); assertEquals(deserialized.getPeople(0).getNumbers(0), number);

7. Заключение

В тази кратка статия въведохме стандарт за описание и съхраняване на данни в двоичен формат - Google Protocol Buffer.

Създадохме прост протокол, създадохме екземпляр на Java, който отговаря на дефинирания протокол. След това видяхме как да сериализираме и десериализираме обекти с помощта на protobuf.

Изпълнението на всички тези примери и кодови фрагменти може да се намери в проекта GitHub - това е проект на Maven, така че трябва да е лесно да се импортира и да се изпълнява както е.