Introdução ao buffer de protocolo do Google
1. Visão geral
Neste artigo, veremosGoogle Protocol Buffer (protobuf) - um formato de dados binários bem conhecido e independente de linguagem. Podemos definir um arquivo com um protocolo e, em seguida, usando esse protocolo, podemos gerar código em linguagens como Java, C ++, C #, Go ou Python.
Este é um artigo introdutório ao formato em si; se você quiser ver como usar o formato com um aplicativo da web Spring, dê uma olhada emthis article.
2. Definindo Dependências Maven
Para usar buffers de protocolo em Java, precisamos adicionar uma dependência Maven a umprotobuf-java:
com.google.protobuf
protobuf-java
${protobuf.version}
3.2.0
3. Definindo um protocolo
Vamos começar com um exemplo. Podemos definir um protocolo muito simples em um formato protobuf:
message Person {
required string name = 1;
}
Este é um protocolo de uma mensagem simples do tipoPerson que possui apenas um campo obrigatório - nome que possui um tipostring.
Vejamos o exemplo mais complexo de definição de um protocolo. Digamos que precisamos armazenar os detalhes da pessoa em um formato protobuf:
pacote protobuf;
package protobuf;
option java_package = "com.example.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;
}
Nosso protocolo consiste em dois tipos de dados: aPersone umAddressBook. Depois de gerar o código (mais sobre isso na seção posterior), essas classes serão as classes internas dentro deAddressBookProtos classe.
Quando queremos definir um campo que é obrigatório - o que significa que criar um objeto sem tal campo causaráException, precisamos usar uma palavra-chaverequired.
Criar um campo com a palavra-chaveoptional significa que esse campo não precisa ser definido. A palavra-chaverepeated é um tipo de array de tamanho variável.
Todos os campos são indexados - o campo indicado com o número 1 será salvo como o primeiro campo em um arquivo binário. O campo marcado com 2 será salvo a seguir e assim por diante. Isso nos dá um melhor controle sobre como os campos são dispostos na memória.
4. Gerando código Java a partir de um arquivo Protobuf
Depois de definir um arquivo, podemos gerar código a partir dele.
Primeiramente, precisamosinstall protobuf em nossa máquina. Depois de fazer isso, podemos gerar o código executando um comandoprotoc:
protoc -I=. --java_out=. addressbook.proto
O comandoprotoc irá gerar o arquivo de saída Java do nosso arquivoaddressbook.proto. A opção-I especifica um diretório no qual reside um arquivoproto. Ojava-out especifica um diretório onde a classe gerada será criada. __
A classe gerada terá setters, getters, construtores e construtores para nossas mensagens definidas. Ele também terá alguns métodos util para salvar arquivos protobuf e desserializá-los do formato binário para a classe Java.
5. Criação de uma instância de mensagens definidas por Protobuf
Podemos facilmente usar um código gerado para criar uma instância Java de uma classePerson:
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);
Podemos criar um construtor fluente usando um métodonewBuilder() no tipo de mensagem desejado. Depois de configurar todos os campos obrigatórios, podemos chamar um métodobuild() para criar uma instância de uma classePerson.
6. Serializando e desserializando o protobuf
Depois de criarmos uma instância de nossa classePerson, queremos salvá-la em um disco em um formato binário compatível com um protocolo criado. Digamos que desejamos criar uma instância da classeAddressBook e adicionar uma pessoa a esse objeto.
Em seguida, queremos salvar esse arquivo no disco - há um método utilwriteTo() em código gerado automaticamente que podemos usar:
AddressBookProtos.AddressBook addressBook
= AddressBookProtos.AddressBook.newBuilder().addPeople(person).build();
FileOutputStream fos = new FileOutputStream(filePath);
addressBook.writeTo(fos);
Depois de executar esse método, nosso objeto será serializado em formato binário e salvo em disco. Para carregar os dados de um disco e desserializar de volta para o objetoAddressBook, podemos usar um métodomergeFrom():
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. Conclusão
Neste rápido artigo, introduzimos um padrão para descrever e armazenar dados em um formato binário - Google Protocol Buffer.
Criamos um protocolo simples, criamos uma instância Java que cumpre o protocolo definido. Em seguida, vimos como serializar e desserializar objetos usando o protobuf.
A implementação de todos esses exemplos e trechos de código pode ser encontrada emGitHub project - este é um projeto Maven, portanto, deve ser fácil de importar e executar como está.