Netty with protobuf(一)

房东的猫 提交于 2019-12-10 07:54:00

Netty with protobuf

这是一篇关于netty和protobuf2的文章,先来介绍一下protobuf的简单使用。网上有很多基本的protobuf的介绍,这里就不在赘述了。


protobuf官网上提供了一个例子,我们就拿那个例子来改造:

proto文件描述了消息的结构,这个文件时这样的

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 phone = 4;
}

message AddressBook {
  repeated Person person = 1;
}


我们现在通过protobuf提供的源代码编译器生成我们的Java代码

E:\tools2\protobuf>protoc.exe -I=E:\test-protobuf --java_out=E:\test-protobuf E:\test-protobuf\addressbook.proto

-I表示指定proto文件的目录位置,--java-out表示输出Java源代码的目录位置,后跟的参数表示文件的路径


现在在你所指定的目录下有一个Java类文件,就是AddressBookProtos.java文件。

通过这个类可以把这个类序列化,看示例代码:

@Test
public void test() throws IOException {
    AddressBookProtos.AddressBook.Builder addressBookBuilder = AddressBookProtos.AddressBook.newBuilder();


    AddressBookProtos.Person.PhoneNumber.Builder phoneNumberBuilder = AddressBookProtos.
            Person.PhoneNumber.newBuilder();

    AddressBookProtos.Person.Builder personBuilder = AddressBookProtos.Person.newBuilder();
    personBuilder.setEmail("744858873@qq.com").setId(123456789).setName("hellolyx");
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330465").setType(AddressBookProtos.Person.PhoneType.HOME).build());
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330466").setType(AddressBookProtos.Person.PhoneType.WORK).build());
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330467").setType(AddressBookProtos.Person.PhoneType.MOBILE).build());
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330468").setType(AddressBookProtos.Person.PhoneType.MOBILE).build());
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330469").setType(AddressBookProtos.Person.PhoneType.MOBILE).build());
    personBuilder.setPhone(0, phoneNumberBuilder.setNumber("110").setType(AddressBookProtos.Person.PhoneType.MOBILE).build());

    //向电话薄里添加一个联系人
    addressBookBuilder.addPerson(personBuilder.build());

    personBuilder.setEmail("78655676@qq.com").setId(123456789).setName("hellodog");
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330465").setType(AddressBookProtos.Person.PhoneType.HOME).build());
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330466").setType(AddressBookProtos.Person.PhoneType.WORK).build());
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330467").setType(AddressBookProtos.Person.PhoneType.MOBILE).build());
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330468").setType(AddressBookProtos.Person.PhoneType.MOBILE).build());
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330469").setType(AddressBookProtos.Person.PhoneType.MOBILE).build());
    personBuilder.setPhone(0, phoneNumberBuilder.setNumber("119").setType(AddressBookProtos.Person.PhoneType.MOBILE).build());

    //再次向电话薄里添加一个联系人
    addressBookBuilder.addPerson(personBuilder.build());

    personBuilder.setEmail("78655676@qq.com").setId(123456789).setName("hellopig");
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330465").setType(AddressBookProtos.Person.PhoneType.HOME).build());
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330466").setType(AddressBookProtos.Person.PhoneType.WORK).build());
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330467").setType(AddressBookProtos.Person.PhoneType.MOBILE).build());
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330468").setType(AddressBookProtos.Person.PhoneType.MOBILE).build());
    personBuilder.addPhone(phoneNumberBuilder.setNumber("15840330469").setType(AddressBookProtos.Person.PhoneType.MOBILE).build());
    personBuilder.setPhone(0, phoneNumberBuilder.setNumber("124").setType(AddressBookProtos.Person.PhoneType.MOBILE).build());

    addressBookBuilder.addPerson(personBuilder.build());

    /**
     * 一个电话薄里添加了三个人
     */

    byte[] book = addressBookBuilder.build().toByteArray();
    String path = "E:\\test-protobuf\\test.txt";
    FileOutputStream fileOutputStream = new FileOutputStream(path);
    fileOutputStream.write(book);
    fileOutputStream.close();

    //反序列化
    AddressBookProtos.AddressBook b = AddressBookProtos.AddressBook.parseFrom(book);
    System.out.println(b.toString());
}

这是通过proto.exe生成的Java类的基本用法,最后打印出来的信息略。

通过这种方式,你可以发现序列化一个类是不是很方便啊,并且序列化和反序列有很好的性能,同时序列后的数据量很小。

在上个例子中,我们吧序列化后的数据保存在了txt文件中,现在可以通过读取这个文本文件反序列化。

/**
 * 在运行时确定消息格式,动态生成消息
 */
@Test
public void test8876() throws IOException {
    String messagePath = "E:\\test-protobuf\\test.txt";
    FileInputStream fileInputStream = new FileInputStream(messagePath);
    byte[] message = new byte[fileInputStream.available()];
    fileInputStream.read(message);

    Descriptors.FileDescriptor fileDescriptor = AddressBookProtos.getDescriptor();
    Descriptors.Descriptor addressBookDescriptor = fileDescriptor.findMessageTypeByName("AddressBook");
    DynamicMessage addressBook = DynamicMessage.parseFrom(addressBookDescriptor, message);
    System.out.println(addressBook.toString());
}

这就是基本的protobuf-java类库的基本使用方法。对于protobuf的自描述消息还没有研究的很透彻,等研究明白了,再把那个发上来。

====END====

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!