Einführung in Google Protocol Buffer

1. Übersicht

In diesem Artikel betrachten wir den Google Protocol Buffer (protobuf) - ein bekanntes sprachunabhängiges Binärdatenformat. Wir können eine Datei mit einem Protokoll definieren und als nächstes mit diesem Protokoll Code in Sprachen wie Java, C ++, C #, Go oder Python generieren.

Dies ist ein Einführungsartikel zum Format selbst; Wenn Sie wissen möchten, wie das Format mit einer Spring-Webanwendung verwendet wird, lesen Sie diesen Artikel.

2. Definieren von Maven-Abhängigkeiten

Um Protokollpuffer in Java zu verwenden, müssen wir einem Protobuf-Java eine Maven-Abhängigkeit hinzufügen:

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

3. Definieren eines Protokolls

Beginnen wir mit einem Beispiel. Wir können ein sehr einfaches Protokoll in einem Protobuf-Format definieren:

message Person { required string name = 1; }

Dies ist ein Protokoll einer einfachen Nachricht vom Typ Person , die nur ein erforderliches Feld enthält - Name, der einen Zeichenfolgentyp hat .

Schauen wir uns das komplexere Beispiel für die Definition eines Protokolls an. Angenommen, wir müssen Personendaten in einem Protobuf-Format speichern:

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

Unser Protokoll besteht aus zwei Arten von Daten: einer Person und einem Adressbuch. Nach dem Generieren des Codes (mehr dazu im späteren Abschnitt) sind diese Klassen die inneren Klassen innerhalb der AddressBookProtos- Klasse.

Wenn wir ein Feld definieren möchten, das erforderlich ist - was bedeutet, dass das Erstellen eines Objekts ohne ein solches Feld eine Ausnahme verursacht , müssen wir ein erforderliches Schlüsselwort verwenden.

Wenn Sie ein Feld mit dem optionalen Schlüsselwort erstellen, muss dieses Feld nicht festgelegt werden. Das wiederholte Schlüsselwort ist ein Array-Typ mit variabler Größe.

Alle Felder sind indiziert - das mit Nummer 1 gekennzeichnete Feld wird als erstes Feld in einer Binärdatei gespeichert. Das mit 2 gekennzeichnete Feld wird als nächstes gespeichert und so weiter. Dadurch können wir besser steuern, wie Felder im Speicher angeordnet sind.

4. Generieren von Java-Code aus einer Protobuf-Datei

Sobald wir eine Datei definiert haben, können wir daraus Code generieren.

Zunächst müssen wir protobuf auf unserer Maschine installieren. Sobald wir dies getan haben, können wir Code generieren, indem wir einen Protoc- Befehl ausführen :

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

Der Protoc Befehl Java - Ausgabedatei aus unserer erzeugt addressbook.proto Datei . Die Option -I gibt ein Verzeichnis an, in dem sich eine Protodatei befindet. Das Java-Out gibt ein Verzeichnis an, in dem die generierte Klasse erstellt wird.

Die generierte Klasse verfügt über Setter, Getter, Konstruktoren und Builder für unsere definierten Nachrichten. Es wird auch einige nützliche Methoden zum Speichern und Deserialisieren von Protobuf-Dateien vom Binärformat in die Java-Klasse geben.

5. Erstellen einer Instanz von Protobuf-definierten Nachrichten

Wir können leicht einen generierten Code verwenden, um eine Java-Instanz einer Person- Klasse zu erstellen :

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

Wir können einen fließenden Builder erstellen, indem wir eine newBuilder () -Methode für den gewünschten Nachrichtentyp verwenden. Nachdem Sie alle erforderlichen Felder eingerichtet haben, können Sie eine build () -Methode aufrufen , um eine Instanz einer Person- Klasse zu erstellen .

6. Serialisierung und Deserialisierung von Protobuf

Sobald wir eine Instanz unserer Person- Klasse erstellt haben, möchten wir diese in einem Binärformat auf der Disc speichern, das mit einem erstellten Protokoll kompatibel ist. Angenommen , wir möchten eine Instanz der AddressBook- Klasse erstellen und diesem Objekt eine Person hinzufügen.

Als nächstes wollen wir diese Datei auf einer CD speichern - es gibt eine writeTo () util-Methode in automatisch generiertem Code, die wir verwenden können:

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

Nach Ausführung dieser Methode wird unser Objekt in das Binärformat serialisiert und auf der Disc gespeichert. Um diese Daten von einer Disc zu laden und wieder in das AddressBook- Objekt zu deserialisieren, können Sie eine mergeFrom () -Methode verwenden:

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. Fazit

In diesem kurzen Artikel haben wir einen Standard zum Beschreiben und Speichern von Daten in einem Binärformat eingeführt - Google Protocol Buffer.

Wir haben ein einfaches Protokoll erstellt und eine Java-Instanz erstellt, die dem definierten Protokoll entspricht. Als nächstes haben wir gesehen, wie Objekte mit Protobuf serialisiert und deserialisiert werden.

Die Implementierung all dieser Beispiele und Codefragmente finden Sie im GitHub-Projekt - dies ist ein Maven-Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.