Netty系列化之Google Protobuf编解码

Posted 落叶飞翔的蜗牛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Netty系列化之Google Protobuf编解码相关的知识,希望对你有一定的参考价值。

内容目录

Protobuf 简介Protobuf 下载Protobuf 安装编写message.proto文件编译message.proto文件编译后的得到的Message.java测试代码测试结果

Protobuf 简介

  • 轻便高效的结构化数据存储格式

  • 更小、更快、更简洁

  • C++、Java、Python 三种语言的 API

Protobuf 下载

https://github.com/protocolbuffers/protobuf/releases/tag/v3.6.1

Protobuf 安装

tar -xzf protobuf-2.1.0.tar.gz 

cd protobuf

./configure

make 

make check 

make install

编写message.proto文件

syntax = "proto3";

message Person {
    int32 id = 1;
    string name = 2;

    repeated Phone phone = 4;

    enum PhoneType {
        MOBILE = 0;
        HOME = 1;
        WORK = 2;
    }

    message Phone {
        string number = 1;
        PhoneType type = 2;
    }
}

编译message.proto文件

protobuf安装完毕后,根目录会出现protoc文件

protoc --java_out=./data ./data/message.proto

-I 后面是proto文件所在的目录 
–java_out 后面是生成java文件存放地址 
最后一个参数是proto文件的名称

编译后的得到的Message.java

public final class Message {
  private Message() {}
  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistryLite registry) {
  }

  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistry registry) {
    registerAllExtensions(
        (com.google.protobuf.ExtensionRegistryLite) registry);
  }
  public interface PersonOrBuilder extends
      // @@protoc_insertion_point(interface_extends:Person)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>int32 id = 1;</code>
     */

    int getId();

    /**
     * <code>string name = 2;</code>
     */

    String getName();
    /**
     * <code>string name = 2;</code>
     */

    com.google.protobuf.ByteString
        getNameBytes();

    /**
     * <code>repeated .Person.Phone phone = 4;</code>
     */

    java.util.List<Person.Phone>
        getPhoneList();
    /**
     * <code>repeated .Person.Phone phone = 4;</code>
     */

    Person.Phone getPhone(int index);
    /**
     * <code>repeated .Person.Phone phone = 4;</code>
     */

    int getPhoneCount();
    /**
     * <code>repeated .Person.Phone phone = 4;</code>
     */

    java.util.List<? extends Person.PhoneOrBuilder>
        getPhoneOrBuilderList();
    /**
     * <code>repeated .Person.Phone phone = 4;</code>
     */

    Person.PhoneOrBuilder getPhoneOrBuilder(
            int index);
  }
  /**
   * Protobuf type {@code Person}
   */

  public  static final class Person extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:Person)
      PersonOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use Person.newBuilder() to construct.
    private Person(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private Person() {
      id_ = 0;
      name_ = "";
      phone_ = java.util.Collections.emptyList();
    }

    @Override
    public final com.google.protobuf.UnknownFieldSet
    getUnknownFields() {
      return this.unknownFields;
    }
    private Person(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      this();
      if (extensionRegistry == null) {
        throw new NullPointerException();
      }
      int mutable_bitField0_ = 0;
      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
          com.google.protobuf.UnknownFieldSet.newBuilder();
      try {
        boolean done = false;
        while (!done) {
          int tag = input.readTag();
          switch (tag) {
            case 0:
              done = true;
              break;
            case 8: {

              id_ = input.readInt32();
              break;
            }
            case 18: {
              String s = input.readStringRequireUtf8();

              name_ = s;
              break;
            }
            case 34: {
              if (!((mutable_bitField0_ & 0x00000004) == 0x00000004)) {
                phone_ = new java.util.ArrayList<Phone>();
                mutable_bitField0_ |= 0x00000004;
              }
              phone_.add(
                  input.readMessage(Phone.parser(), extensionRegistry));
              break;
            }
            default: {
              if (!parseUnknownFieldProto3(
                  input, unknownFields, extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e).setUnfinishedMessage(this);
      } finally {
        if (((mutable_bitField0_ & 0x00000004) == 0x00000004)) {
          phone_ = java.util.Collections.unmodifiableList(phone_);
        }
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return Message.internal_static_Person_descriptor;
    }

    @Override
    protected FieldAccessorTable
        internalGetFieldAccessorTable() {
      return Message.internal_static_Person_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              Person.class, Builder.class);
    }

    /**
     * Protobuf enum {@code Person.PhoneType}
     */

    public enum PhoneType
        implements com.google.protobuf.ProtocolMessageEnum {
      /**
       * <code>MOBILE = 0;</code>
       */

      MOBILE(0),
      /**
       * <code>HOME = 1;</code>
       */

      HOME(1),
      /**
       * <code>WORK = 2;</code>
       */

      WORK(2),
      UNRECOGNIZED(-1),
      ;

      /**
       * <code>MOBILE = 0;</code>
       */

      public static final int MOBILE_VALUE = 0;
      /**
       * <code>HOME = 1;</code>
       */

      public static final int HOME_VALUE = 1;
      /**
       * <code>WORK = 2;</code>
       */

      public static final int WORK_VALUE = 2;


      public final int getNumber() {
        if (this == UNRECOGNIZED) {
          throw new IllegalArgumentException(
              "Can't get the number of an unknown enum value.");
        }
        return value;
      }

      /**
       * @deprecated Use {@link #forNumber(int)} instead.
       */

      @Deprecated
      public static PhoneType valueOf(int value) {
        return forNumber(value);
      }

      public static PhoneType forNumber(int value) {
        switch (value) {
          case 0return MOBILE;
          case 1return HOME;
          case 2return WORK;
          defaultreturn null;
        }
      }

      public static com.google.protobuf.Internal.EnumLiteMap<PhoneType>
          internalGetValueMap() {
        return internalValueMap;
      }
      private static final com.google.protobuf.Internal.EnumLiteMap<
          PhoneType> internalValueMap =
            new com.google.protobuf.Internal.EnumLiteMap<PhoneType>() {
              public PhoneType findValueByNumber(int number) {
                return PhoneType.forNumber(number);
              }
            };

      public final com.google.protobuf.Descriptors.EnumValueDescriptor
          getValueDescriptor() {
        return getDescriptor().getValues().get(ordinal());
      }
      public final com.google.protobuf.Descriptors.EnumDescriptor
          getDescriptorForType() {
        return getDescriptor();
      }
      public static final com.google.protobuf.Descriptors.EnumDescriptor
          getDescriptor() {
        return Person.getDescriptor().getEnumTypes().get(0);
      }

      private static final PhoneType[] VALUES = values();

      public static PhoneType valueOf(
          com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
        if (desc.getType() != getDescriptor()) {
          throw new IllegalArgumentException(
            "EnumValueDescriptor is not for this type.");
        }
        if (desc.getIndex() == -1) {
          return UNRECOGNIZED;
        }
        return VALUES[desc.getIndex()];
      }

      private final int value;

      private PhoneType(int value) {
        this.value = value;
      }

      // @@protoc_insertion_point(enum_scope:Person.PhoneType)
    }

    public interface PhoneOrBuilder extends
        // @@protoc_insertion_point(interface_extends:Person.Phone)
        com.google.protobuf.MessageOrBuilder {

      /**
       * <code>string number = 1;</code>
       */

      String getNumber();
      /**
       * <code>string number = 1;</code>
       */

      com.google.protobuf.ByteString
          getNumberBytes();

      /**
       * <code>.Person.PhoneType type = 2;</code>
       */

      int getTypeValue();
      /**
       * <code>.Person.PhoneType type = 2;</code>
       */

      PhoneType getType();
    }
    /**
     * Protobuf type {@code Person.Phone}
     */

    public  static final class Phone extends
        com.google.protobuf.GeneratedMessageV3 implements
        // @@protoc_insertion_point(message_implements:Person.Phone)
        PhoneOrBuilder {
    private static final long serialVersionUID = 0L;
      // Use Phone.newBuilder() to construct.
      private Phone(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
        super(builder);
      }
      private Phone() {
        number_ = "";
        type_ = 0;
      }

      @Override
      public final com.google.protobuf.UnknownFieldSet
      getUnknownFields() {
        return this.unknownFields;
      }
      private Phone(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        this();
        if (extensionRegistry == null) {
          throw new NullPointerException();
        }
        int mutable_bitField0_ = 0;
        com.google.protobuf.UnknownFieldSet.Builder unknownFields =
            com.google.protobuf.UnknownFieldSet.newBuilder();
        try {
          boolean done = false;
          while (!done) {
            int tag = input.readTag();
            switch (tag) {
              case 0:
                done = true;
                break;
              case 10: {
                String s = input.readStringRequireUtf8();

                number_ = s;
                break;
              }
              case 16: {
                int rawValue = input.readEnum();

                type_ = rawValue;
                break;
              }
              default: {
                if (!parseUnknownFieldProto3(
                    input, unknownFields, extensionRegistry, tag)) {
                  done = true;
                }
                break;
              }
            }
          }
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.setUnfinishedMessage(this);
        } catch (java.io.IOException e) {
          throw new com.google.protobuf.InvalidProtocolBufferException(
              e).setUnfinishedMessage(this);
        } finally {
          this.unknownFields = unknownFields.build();
          makeExtensionsImmutable();
        }
      }
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return Message.internal_static_Person_Phone_descriptor;
      }

      @Override
      protected FieldAccessorTable
          internalGetFieldAccessorTable() {
        return Message.internal_static_Person_Phone_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                Phone.class, Builder.class);
      }

      public static final int NUMBER_FIELD_NUMBER = 1;
      private volatile Object number_;
      /**
       * <code>string number = 1;</code>
       */

      public String getNumber() {
        Object ref = number_;
        if (ref instanceof String) {
          return (String) ref;
        } else {
          com.google.protobuf.ByteString bs = 
              (com.google.protobuf.ByteString) ref;
          String s = bs.toStringUtf8();
          number_ = s;
          return s;
        }
      }
      /**
       * <code>string number = 1;</code>
       */

      public com.google.protobuf.ByteString
          getNumberBytes() {
        Object ref = number_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (String) ref);
          number_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }

      public static final int TYPE_FIELD_NUMBER = 2;
      private int type_;
      /**
       * <code>.Person.PhoneType type = 2;</code>
       */

      public int getTypeValue() {
        return type_;
      }
      /**
       * <code>.Person.PhoneType type = 2;</code>
       */

      public PhoneType getType() {
        @SuppressWarnings("deprecation")
        PhoneType result = PhoneType.valueOf(type_);
        return result == null ? PhoneType.UNRECOGNIZED : result;
      }

      private byte memoizedIsInitialized = -1;
      @Override
      public final boolean isInitialized() {
        byte isInitialized = memoizedIsInitialized;
        if (isInitialized == 1return true;
        if (isInitialized == 0return false;

        memoizedIsInitialized = 1;
        return true;
      }

      @Override
      public void writeTo(com.google.protobuf.CodedOutputStream output)
                          throws java.io.IOException {
        if (!getNumberBytes().isEmpty()) {
          com.google.protobuf.GeneratedMessageV3.writeString(output, 1, number_);
        }
        if (type_ != PhoneType.MOBILE.getNumber()) {
          output.writeEnum(2, type_);
        }
        unknownFields.writeTo(output);
      }

      @Override
      public int getSerializedSize() {
        int size = memoizedSize;
        if (size != -1return size;

        size = 0;
        if (!getNumberBytes().isEmpty()) {
          size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, number_);
        }
        if (type_ != PhoneType.MOBILE.getNumber()) {
          size += com.google.protobuf.CodedOutputStream
            .computeEnumSize(2, type_);
        }
        size += unknownFields.getSerializedSize();
        memoizedSize = size;
        return size;
      }

      @Override
      public boolean equals(final Object obj) {
        if (obj == this) {
         return true;
        }
        if (!(obj instanceof Phone)) {
          return super.equals(obj);
        }
        Phone other = (Phone) obj;

        boolean result = true;
        result = result && getNumber()
            .equals(other.getNumber());
        result = result && type_ == other.type_;
        result = result && unknownFields.equals(other.unknownFields);
        return result;
      }

     ······此处省去N行代码······

   

  // @@protoc_insertion_point(outer_class_scope)
}

测试代码

public class Main {
    public static void main(String[] args{
        Message.Person.Builder personBuilder = Message.Person.newBuilder();
        personBuilder.setId(12345678);
        personBuilder.setName("Admin");
        personBuilder.addPhone(Message.Person.Phone.newBuilder().setNumber("10010").setType(Message.Person.PhoneType.MOBILE));
        personBuilder.addPhone(Message.Person.Phone.newBuilder().setNumber("10086").setType(Message.Person.PhoneType.HOME));
        personBuilder.addPhone(Message.Person.Phone.newBuilder().setNumber("10000").setType(Message.Person.PhoneType.WORK));

        Message.Person person = personBuilder.build();
        byte[] buff = person.toByteArray();

        try {
            Message.Person personOut = Message.Person.parseFrom(buff);
            System.out.printf("Id:%d, Name:%s\n", personOut.getId(), personOut.getName());

            List<Message.Person.Phone> phoneList = personOut.getPhoneList();

            for (Message.Person.Phone phone : phoneList) {
                System.out.printf("PhoneNumber:%s (%s)\n", phone.getNumber(), phone.getType());
            }

        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }
        //Person类的字节码
        System.out.println(Arrays.toString(buff));

    }
}

测试结果

Id:12345678Name:Admin
PhoneNumber:10010 (MOBILE)
PhoneNumber:10086 (HOME)
PhoneNumber:10000 (WORK)
[8, -50, -62, -15, 5, 18, 5, 65, 100, 109, 105, 110, 34, 7, 10, 5, 49, 48, 48, 49, 48, 34, 9, 10, 5, 49, 48, 48, 56, 54, 16, 1, 34, 9, 10, 5, 49, 48, 48, 48, 48, 16, 2]


以上是关于Netty系列化之Google Protobuf编解码的主要内容,如果未能解决你的问题,请参考以下文章

netty编解码之使用protobuf

netty系列之:在netty中使用protobuf协议

netty编解码之java原生序列化

netty编解码之jboss marshalling

Netty-整合Protobuf高性能数据传输

Netty学习4(学习笔记)