找回密码
 立即注册
首页 业界区 业界 高效编解码协议之protobuf协议详解

高效编解码协议之protobuf协议详解

肿抢 2025-8-1 20:18:36
Protocol Buffers(简称 protobuf)是 Google 开发的 高效二进制序列化工具,用于结构化数据的存储和传输。
核心特性

特性说明跨语言支持支持 Java、C++、Python、Go 等主流语言。高效编解码二进制格式,比 JSON/XML 更小、更快。强类型约束通过 .proto 文件定义数据结构,避免运行时错误。向后兼容支持字段扩展(新增字段不影响旧代码)。使用指南

开发环境


  • windows
  • jetbrains idea
  • maven_3.9.7
  • jdk_8
  • protobuf_31.1
安装编译器(protoc)


  • 下载地址: protobuf_v31.1
配置


  • 将下载的压缩包解压出来,新增环境变量protobuf=文件夹路径
  • 编辑环境变量Path,新增%protobuf%\bin
验证
  1. # 打开cmd命令行,执行以下命令
  2. protoc --version
  3. # 输出结果如下,表示安装成功
  4. libprotoc 31.1
复制代码
定义数据结构


  • 新建person.proto文件
  1. // person.proto
  2. syntax = "proto3";
  3. message Person {
  4.   string name = 1;
  5.   int32 id = 2;
  6.   repeated string emails = 3;
  7. }
复制代码
编译

手动执行命令
  1. # 打开cmd命令行,切换到person.proto文件目录下,执行以下命令
  2. protoc --java_out=./ ./person.proto
  3. # 当前目录下会生成PersonOuterClass.java文件
  4. # 将PersonOuterClass.java复制到对应项目目录就可以使用了
  5. # PersonOuterClass.java默认没有package路径,需要手动加一下
复制代码
maven插件编译


  • 在pom.xml中加入以下代码,执行maven的clean compile
  1. <build>
  2.   <plugins>
  3.     <plugin>
  4.       <groupId>org.xolstice.maven.plugins</groupId>
  5.       protobuf-maven-plugin</artifactId>
  6.       <version>0.6.1</version>
  7.       <executions>
  8.         <execution>
  9.           <goals>
  10.             <goal>compile</goal>
  11.           </goals>
  12.         </execution>
  13.       </executions>
  14.       <configuration>
  15.         
  16.         <protocExecutable>protoc</protocExecutable>
  17.         
  18.         
  19.       </configuration>
  20.     </plugin>
  21.   </plugins>
  22. </build>
复制代码

  • 插件默认读取文件夹/src/main/proto下的proto文件去编译
  • 在文件夹target/generated-sources/protobuf/java下会生成对应pojo的protobuf操作类
注意:

  • 若执行protoc命令之后idea报如下错误:Module 'my-test' production: java.lang.ClassCastException: class org.jetbrains.jps.builders.java.dependencyView.TypeRepr$PrimitiveType cannot be cast to class org.jetbrains.jps.builders.java.dependencyView.TypeRepr$ClassType (org.jetbrains.jps.builders.java.dependencyView.TypeRepr$PrimitiveType and org.jetbrains.jps.builders.java.dependencyView.TypeRepr$ClassType are in unnamed module of loader java.net.URLClassLoader @2f2c9b19)。则清除一下idea的缓存,然后执行rebuild
  • 若idea的terminal或者maven执行compile的时候报错未找到protoc命令,则可以在terminal中执行以下命令排查idea是否读取到最新的Path。若打印的Path值没有protoc的路径,则重启一下电脑。
  1. # terminal中使用的是powershell的话执行
  2. echo $env:path
  3. # terminal中使用的是cmd的话执行
  4. echo %path%
复制代码
编译结果示例
  1. // Generated by the protocol buffer compiler.  DO NOT EDIT!
  2. // NO CHECKED-IN PROTOBUF GENCODE
  3. // source: person.proto
  4. // Protobuf Java Version: 4.31.1
  5. @com.google.protobuf.Generated
  6. public final class PersonOuterClass {
  7.   private PersonOuterClass() {}
  8.   static {
  9.     com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
  10.       com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
  11.       /* major= */ 4,
  12.       /* minor= */ 31,
  13.       /* patch= */ 1,
  14.       /* suffix= */ "",
  15.       PersonOuterClass.class.getName());
  16.   }
  17.   public static void registerAllExtensions(
  18.       com.google.protobuf.ExtensionRegistryLite registry) {
  19.   }
  20.   public static void registerAllExtensions(
  21.       com.google.protobuf.ExtensionRegistry registry) {
  22.     registerAllExtensions(
  23.         (com.google.protobuf.ExtensionRegistryLite) registry);
  24.   }
  25.   public interface PersonOrBuilder extends
  26.       // @@protoc_insertion_point(interface_extends:Person)
  27.       com.google.protobuf.MessageOrBuilder {
  28.     /**
  29.      * string name = 1;
  30.      * @return The name.
  31.      */
  32.     java.lang.String getName();
  33.     /**
  34.      * string name = 1;
  35.      * @return The bytes for name.
  36.      */
  37.     com.google.protobuf.ByteString
  38.         getNameBytes();
  39.     /**
  40.      * int32 id = 2;
  41.      * @return The id.
  42.      */
  43.     int getId();
  44.     /**
  45.      * repeated string emails = 3;
  46.      * @return A list containing the emails.
  47.      */
  48.     java.util.List<java.lang.String>
  49.         getEmailsList();
  50.     /**
  51.      * repeated string emails = 3;
  52.      * @return The count of emails.
  53.      */
  54.     int getEmailsCount();
  55.     /**
  56.      * repeated string emails = 3;
  57.      * @param index The index of the element to return.
  58.      * @return The emails at the given index.
  59.      */
  60.     java.lang.String getEmails(int index);
  61.     /**
  62.      * repeated string emails = 3;
  63.      * @param index The index of the value to return.
  64.      * @return The bytes of the emails at the given index.
  65.      */
  66.     com.google.protobuf.ByteString
  67.         getEmailsBytes(int index);
  68.   }
  69.   /**
  70.    * Protobuf type {@code Person}
  71.    */
  72.   public static final class Person extends
  73.       com.google.protobuf.GeneratedMessage implements
  74.       // @@protoc_insertion_point(message_implements:Person)
  75.       PersonOrBuilder {
  76.   private static final long serialVersionUID = 0L;
  77.     static {
  78.       com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
  79.         com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
  80.         /* major= */ 4,
  81.         /* minor= */ 31,
  82.         /* patch= */ 1,
  83.         /* suffix= */ "",
  84.         Person.class.getName());
  85.     }
  86.     // Use Person.newBuilder() to construct.
  87.     private Person(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
  88.       super(builder);
  89.     }
  90.     private Person() {
  91.       name_ = "";
  92.       emails_ =
  93.           com.google.protobuf.LazyStringArrayList.emptyList();
  94.     }
  95.     public static final com.google.protobuf.Descriptors.Descriptor
  96.         getDescriptor() {
  97.       return PersonOuterClass.internal_static_Person_descriptor;
  98.     }
  99.     @java.lang.Override
  100.     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
  101.         internalGetFieldAccessorTable() {
  102.       return PersonOuterClass.internal_static_Person_fieldAccessorTable
  103.           .ensureFieldAccessorsInitialized(
  104.               PersonOuterClass.Person.class, PersonOuterClass.Person.Builder.class);
  105.     }
  106.     public static final int NAME_FIELD_NUMBER = 1;
  107.     @SuppressWarnings("serial")
  108.     private volatile java.lang.Object name_ = "";
  109.     /**
  110.      * string name = 1;
  111.      * @return The name.
  112.      */
  113.     @java.lang.Override
  114.     public java.lang.String getName() {
  115.       java.lang.Object ref = name_;
  116.       if (ref instanceof java.lang.String) {
  117.         return (java.lang.String) ref;
  118.       } else {
  119.         com.google.protobuf.ByteString bs =
  120.             (com.google.protobuf.ByteString) ref;
  121.         java.lang.String s = bs.toStringUtf8();
  122.         name_ = s;
  123.         return s;
  124.       }
  125.     }
  126.     /**
  127.      * string name = 1;
  128.      * @return The bytes for name.
  129.      */
  130.     @java.lang.Override
  131.     public com.google.protobuf.ByteString
  132.         getNameBytes() {
  133.       java.lang.Object ref = name_;
  134.       if (ref instanceof java.lang.String) {
  135.         com.google.protobuf.ByteString b =
  136.             com.google.protobuf.ByteString.copyFromUtf8(
  137.                 (java.lang.String) ref);
  138.         name_ = b;
  139.         return b;
  140.       } else {
  141.         return (com.google.protobuf.ByteString) ref;
  142.       }
  143.     }
  144.     public static final int ID_FIELD_NUMBER = 2;
  145.     private int id_ = 0;
  146.     /**
  147.      * int32 id = 2;
  148.      * @return The id.
  149.      */
  150.     @java.lang.Override
  151.     public int getId() {
  152.       return id_;
  153.     }
  154.     public static final int EMAILS_FIELD_NUMBER = 3;
  155.     @SuppressWarnings("serial")
  156.     private com.google.protobuf.LazyStringArrayList emails_ =
  157.         com.google.protobuf.LazyStringArrayList.emptyList();
  158.     /**
  159.      * repeated string emails = 3;
  160.      * @return A list containing the emails.
  161.      */
  162.     public com.google.protobuf.ProtocolStringList
  163.         getEmailsList() {
  164.       return emails_;
  165.     }
  166.     /**
  167.      * repeated string emails = 3;
  168.      * @return The count of emails.
  169.      */
  170.     public int getEmailsCount() {
  171.       return emails_.size();
  172.     }
  173.     /**
  174.      * repeated string emails = 3;
  175.      * @param index The index of the element to return.
  176.      * @return The emails at the given index.
  177.      */
  178.     public java.lang.String getEmails(int index) {
  179.       return emails_.get(index);
  180.     }
  181.     /**
  182.      * repeated string emails = 3;
  183.      * @param index The index of the value to return.
  184.      * @return The bytes of the emails at the given index.
  185.      */
  186.     public com.google.protobuf.ByteString
  187.         getEmailsBytes(int index) {
  188.       return emails_.getByteString(index);
  189.     }
  190.     private byte memoizedIsInitialized = -1;
  191.     @java.lang.Override
  192.     public final boolean isInitialized() {
  193.       byte isInitialized = memoizedIsInitialized;
  194.       if (isInitialized == 1) return true;
  195.       if (isInitialized == 0) return false;
  196.       memoizedIsInitialized = 1;
  197.       return true;
  198.     }
  199.     @java.lang.Override
  200.     public void writeTo(com.google.protobuf.CodedOutputStream output)
  201.                         throws java.io.IOException {
  202.       if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) {
  203.         com.google.protobuf.GeneratedMessage.writeString(output, 1, name_);
  204.       }
  205.       if (id_ != 0) {
  206.         output.writeInt32(2, id_);
  207.       }
  208.       for (int i = 0; i < emails_.size(); i++) {
  209.         com.google.protobuf.GeneratedMessage.writeString(output, 3, emails_.getRaw(i));
  210.       }
  211.       getUnknownFields().writeTo(output);
  212.     }
  213.     @java.lang.Override
  214.     public int getSerializedSize() {
  215.       int size = memoizedSize;
  216.       if (size != -1) return size;
  217.       size = 0;
  218.       if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) {
  219.         size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_);
  220.       }
  221.       if (id_ != 0) {
  222.         size += com.google.protobuf.CodedOutputStream
  223.           .computeInt32Size(2, id_);
  224.       }
  225.       {
  226.         int dataSize = 0;
  227.         for (int i = 0; i < emails_.size(); i++) {
  228.           dataSize += computeStringSizeNoTag(emails_.getRaw(i));
  229.         }
  230.         size += dataSize;
  231.         size += 1 * getEmailsList().size();
  232.       }
  233.       size += getUnknownFields().getSerializedSize();
  234.       memoizedSize = size;
  235.       return size;
  236.     }
  237.     @java.lang.Override
  238.     public boolean equals(final java.lang.Object obj) {
  239.       if (obj == this) {
  240.        return true;
  241.       }
  242.       if (!(obj instanceof PersonOuterClass.Person)) {
  243.         return super.equals(obj);
  244.       }
  245.       PersonOuterClass.Person other = (PersonOuterClass.Person) obj;
  246.       if (!getName()
  247.           .equals(other.getName())) return false;
  248.       if (getId()
  249.           != other.getId()) return false;
  250.       if (!getEmailsList()
  251.           .equals(other.getEmailsList())) return false;
  252.       if (!getUnknownFields().equals(other.getUnknownFields())) return false;
  253.       return true;
  254.     }
  255.     @java.lang.Override
  256.     public int hashCode() {
  257.       if (memoizedHashCode != 0) {
  258.         return memoizedHashCode;
  259.       }
  260.       int hash = 41;
  261.       hash = (19 * hash) + getDescriptor().hashCode();
  262.       hash = (37 * hash) + NAME_FIELD_NUMBER;
  263.       hash = (53 * hash) + getName().hashCode();
  264.       hash = (37 * hash) + ID_FIELD_NUMBER;
  265.       hash = (53 * hash) + getId();
  266.       if (getEmailsCount() > 0) {
  267.         hash = (37 * hash) + EMAILS_FIELD_NUMBER;
  268.         hash = (53 * hash) + getEmailsList().hashCode();
  269.       }
  270.       hash = (29 * hash) + getUnknownFields().hashCode();
  271.       memoizedHashCode = hash;
  272.       return hash;
  273.     }
  274.     public static PersonOuterClass.Person parseFrom(
  275.         java.nio.ByteBuffer data)
  276.         throws com.google.protobuf.InvalidProtocolBufferException {
  277.       return PARSER.parseFrom(data);
  278.     }
  279.     public static PersonOuterClass.Person parseFrom(
  280.         java.nio.ByteBuffer data,
  281.         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
  282.         throws com.google.protobuf.InvalidProtocolBufferException {
  283.       return PARSER.parseFrom(data, extensionRegistry);
  284.     }
  285.     public static PersonOuterClass.Person parseFrom(
  286.         com.google.protobuf.ByteString data)
  287.         throws com.google.protobuf.InvalidProtocolBufferException {
  288.       return PARSER.parseFrom(data);
  289.     }
  290.     public static PersonOuterClass.Person parseFrom(
  291.         com.google.protobuf.ByteString data,
  292.         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
  293.         throws com.google.protobuf.InvalidProtocolBufferException {
  294.       return PARSER.parseFrom(data, extensionRegistry);
  295.     }
  296.     public static PersonOuterClass.Person parseFrom(byte[] data)
  297.         throws com.google.protobuf.InvalidProtocolBufferException {
  298.       return PARSER.parseFrom(data);
  299.     }
  300.     public static PersonOuterClass.Person parseFrom(
  301.         byte[] data,
  302.         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
  303.         throws com.google.protobuf.InvalidProtocolBufferException {
  304.       return PARSER.parseFrom(data, extensionRegistry);
  305.     }
  306.     public static PersonOuterClass.Person parseFrom(java.io.InputStream input)
  307.         throws java.io.IOException {
  308.       return com.google.protobuf.GeneratedMessage
  309.           .parseWithIOException(PARSER, input);
  310.     }
  311.     public static PersonOuterClass.Person parseFrom(
  312.         java.io.InputStream input,
  313.         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
  314.         throws java.io.IOException {
  315.       return com.google.protobuf.GeneratedMessage
  316.           .parseWithIOException(PARSER, input, extensionRegistry);
  317.     }
  318.     public static PersonOuterClass.Person parseDelimitedFrom(java.io.InputStream input)
  319.         throws java.io.IOException {
  320.       return com.google.protobuf.GeneratedMessage
  321.           .parseDelimitedWithIOException(PARSER, input);
  322.     }
  323.     public static PersonOuterClass.Person parseDelimitedFrom(
  324.         java.io.InputStream input,
  325.         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
  326.         throws java.io.IOException {
  327.       return com.google.protobuf.GeneratedMessage
  328.           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
  329.     }
  330.     public static PersonOuterClass.Person parseFrom(
  331.         com.google.protobuf.CodedInputStream input)
  332.         throws java.io.IOException {
  333.       return com.google.protobuf.GeneratedMessage
  334.           .parseWithIOException(PARSER, input);
  335.     }
  336.     public static PersonOuterClass.Person parseFrom(
  337.         com.google.protobuf.CodedInputStream input,
  338.         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
  339.         throws java.io.IOException {
  340.       return com.google.protobuf.GeneratedMessage
  341.           .parseWithIOException(PARSER, input, extensionRegistry);
  342.     }
  343.     @java.lang.Override
  344.     public Builder newBuilderForType() { return newBuilder(); }
  345.     public static Builder newBuilder() {
  346.       return DEFAULT_INSTANCE.toBuilder();
  347.     }
  348.     public static Builder newBuilder(PersonOuterClass.Person prototype) {
  349.       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
  350.     }
  351.     @java.lang.Override
  352.     public Builder toBuilder() {
  353.       return this == DEFAULT_INSTANCE
  354.           ? new Builder() : new Builder().mergeFrom(this);
  355.     }
  356.     @java.lang.Override
  357.     protected Builder newBuilderForType(
  358.         com.google.protobuf.GeneratedMessage.BuilderParent parent) {
  359.       Builder builder = new Builder(parent);
  360.       return builder;
  361.     }
  362.     /**
  363.      * Protobuf type {@code Person}
  364.      */
  365.     public static final class Builder extends
  366.         com.google.protobuf.GeneratedMessage.Builder<Builder> implements
  367.         // @@protoc_insertion_point(builder_implements:Person)
  368.         PersonOuterClass.PersonOrBuilder {
  369.       public static final com.google.protobuf.Descriptors.Descriptor
  370.           getDescriptor() {
  371.         return PersonOuterClass.internal_static_Person_descriptor;
  372.       }
  373.       @java.lang.Override
  374.       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
  375.           internalGetFieldAccessorTable() {
  376.         return PersonOuterClass.internal_static_Person_fieldAccessorTable
  377.             .ensureFieldAccessorsInitialized(
  378.                 PersonOuterClass.Person.class, PersonOuterClass.Person.Builder.class);
  379.       }
  380.       // Construct using PersonOuterClass.Person.newBuilder()
  381.       private Builder() {
  382.       }
  383.       private Builder(
  384.           com.google.protobuf.GeneratedMessage.BuilderParent parent) {
  385.         super(parent);
  386.       }
  387.       @java.lang.Override
  388.       public Builder clear() {
  389.         super.clear();
  390.         bitField0_ = 0;
  391.         name_ = "";
  392.         id_ = 0;
  393.         emails_ =
  394.             com.google.protobuf.LazyStringArrayList.emptyList();
  395.         return this;
  396.       }
  397.       @java.lang.Override
  398.       public com.google.protobuf.Descriptors.Descriptor
  399.           getDescriptorForType() {
  400.         return PersonOuterClass.internal_static_Person_descriptor;
  401.       }
  402.       @java.lang.Override
  403.       public PersonOuterClass.Person getDefaultInstanceForType() {
  404.         return PersonOuterClass.Person.getDefaultInstance();
  405.       }
  406.       @java.lang.Override
  407.       public PersonOuterClass.Person build() {
  408.         PersonOuterClass.Person result = buildPartial();
  409.         if (!result.isInitialized()) {
  410.           throw newUninitializedMessageException(result);
  411.         }
  412.         return result;
  413.       }
  414.       @java.lang.Override
  415.       public PersonOuterClass.Person buildPartial() {
  416.         PersonOuterClass.Person result = new PersonOuterClass.Person(this);
  417.         if (bitField0_ != 0) { buildPartial0(result); }
  418.         onBuilt();
  419.         return result;
  420.       }
  421.       private void buildPartial0(PersonOuterClass.Person result) {
  422.         int from_bitField0_ = bitField0_;
  423.         if (((from_bitField0_ & 0x00000001) != 0)) {
  424.           result.name_ = name_;
  425.         }
  426.         if (((from_bitField0_ & 0x00000002) != 0)) {
  427.           result.id_ = id_;
  428.         }
  429.         if (((from_bitField0_ & 0x00000004) != 0)) {
  430.           emails_.makeImmutable();
  431.           result.emails_ = emails_;
  432.         }
  433.       }
  434.       @java.lang.Override
  435.       public Builder mergeFrom(com.google.protobuf.Message other) {
  436.         if (other instanceof PersonOuterClass.Person) {
  437.           return mergeFrom((PersonOuterClass.Person)other);
  438.         } else {
  439.           super.mergeFrom(other);
  440.           return this;
  441.         }
  442.       }
  443.       public Builder mergeFrom(PersonOuterClass.Person other) {
  444.         if (other == PersonOuterClass.Person.getDefaultInstance()) return this;
  445.         if (!other.getName().isEmpty()) {
  446.           name_ = other.name_;
  447.           bitField0_ |= 0x00000001;
  448.           onChanged();
  449.         }
  450.         if (other.getId() != 0) {
  451.           setId(other.getId());
  452.         }
  453.         if (!other.emails_.isEmpty()) {
  454.           if (emails_.isEmpty()) {
  455.             emails_ = other.emails_;
  456.             bitField0_ |= 0x00000004;
  457.           } else {
  458.             ensureEmailsIsMutable();
  459.             emails_.addAll(other.emails_);
  460.           }
  461.           onChanged();
  462.         }
  463.         this.mergeUnknownFields(other.getUnknownFields());
  464.         onChanged();
  465.         return this;
  466.       }
  467.       @java.lang.Override
  468.       public final boolean isInitialized() {
  469.         return true;
  470.       }
  471.       @java.lang.Override
  472.       public Builder mergeFrom(
  473.           com.google.protobuf.CodedInputStream input,
  474.           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
  475.           throws java.io.IOException {
  476.         if (extensionRegistry == null) {
  477.           throw new java.lang.NullPointerException();
  478.         }
  479.         try {
  480.           boolean done = false;
  481.           while (!done) {
  482.             int tag = input.readTag();
  483.             switch (tag) {
  484.               case 0:
  485.                 done = true;
  486.                 break;
  487.               case 10: {
  488.                 name_ = input.readStringRequireUtf8();
  489.                 bitField0_ |= 0x00000001;
  490.                 break;
  491.               } // case 10
  492.               case 16: {
  493.                 id_ = input.readInt32();
  494.                 bitField0_ |= 0x00000002;
  495.                 break;
  496.               } // case 16
  497.               case 26: {
  498.                 java.lang.String s = input.readStringRequireUtf8();
  499.                 ensureEmailsIsMutable();
  500.                 emails_.add(s);
  501.                 break;
  502.               } // case 26
  503.               default: {
  504.                 if (!super.parseUnknownField(input, extensionRegistry, tag)) {
  505.                   done = true; // was an endgroup tag
  506.                 }
  507.                 break;
  508.               } // default:
  509.             } // switch (tag)
  510.           } // while (!done)
  511.         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
  512.           throw e.unwrapIOException();
  513.         } finally {
  514.           onChanged();
  515.         } // finally
  516.         return this;
  517.       }
  518.       private int bitField0_;
  519.       private java.lang.Object name_ = "";
  520.       /**
  521.        * string name = 1;
  522.        * @return The name.
  523.        */
  524.       public java.lang.String getName() {
  525.         java.lang.Object ref = name_;
  526.         if (!(ref instanceof java.lang.String)) {
  527.           com.google.protobuf.ByteString bs =
  528.               (com.google.protobuf.ByteString) ref;
  529.           java.lang.String s = bs.toStringUtf8();
  530.           name_ = s;
  531.           return s;
  532.         } else {
  533.           return (java.lang.String) ref;
  534.         }
  535.       }
  536.       /**
  537.        * string name = 1;
  538.        * @return The bytes for name.
  539.        */
  540.       public com.google.protobuf.ByteString
  541.           getNameBytes() {
  542.         java.lang.Object ref = name_;
  543.         if (ref instanceof String) {
  544.           com.google.protobuf.ByteString b =
  545.               com.google.protobuf.ByteString.copyFromUtf8(
  546.                   (java.lang.String) ref);
  547.           name_ = b;
  548.           return b;
  549.         } else {
  550.           return (com.google.protobuf.ByteString) ref;
  551.         }
  552.       }
  553.       /**
  554.        * string name = 1;
  555.        * @param value The name to set.
  556.        * @return This builder for chaining.
  557.        */
  558.       public Builder setName(
  559.           java.lang.String value) {
  560.         if (value == null) { throw new NullPointerException(); }
  561.         name_ = value;
  562.         bitField0_ |= 0x00000001;
  563.         onChanged();
  564.         return this;
  565.       }
  566.       /**
  567.        * string name = 1;
  568.        * @return This builder for chaining.
  569.        */
  570.       public Builder clearName() {
  571.         name_ = getDefaultInstance().getName();
  572.         bitField0_ = (bitField0_ & ~0x00000001);
  573.         onChanged();
  574.         return this;
  575.       }
  576.       /**
  577.        * string name = 1;
  578.        * @param value The bytes for name to set.
  579.        * @return This builder for chaining.
  580.        */
  581.       public Builder setNameBytes(
  582.           com.google.protobuf.ByteString value) {
  583.         if (value == null) { throw new NullPointerException(); }
  584.         checkByteStringIsUtf8(value);
  585.         name_ = value;
  586.         bitField0_ |= 0x00000001;
  587.         onChanged();
  588.         return this;
  589.       }
  590.       private int id_ ;
  591.       /**
  592.        * int32 id = 2;
  593.        * @return The id.
  594.        */
  595.       @java.lang.Override
  596.       public int getId() {
  597.         return id_;
  598.       }
  599.       /**
  600.        * int32 id = 2;
  601.        * @param value The id to set.
  602.        * @return This builder for chaining.
  603.        */
  604.       public Builder setId(int value) {
  605.         id_ = value;
  606.         bitField0_ |= 0x00000002;
  607.         onChanged();
  608.         return this;
  609.       }
  610.       /**
  611.        * int32 id = 2;
  612.        * @return This builder for chaining.
  613.        */
  614.       public Builder clearId() {
  615.         bitField0_ = (bitField0_ & ~0x00000002);
  616.         id_ = 0;
  617.         onChanged();
  618.         return this;
  619.       }
  620.       private com.google.protobuf.LazyStringArrayList emails_ =
  621.           com.google.protobuf.LazyStringArrayList.emptyList();
  622.       private void ensureEmailsIsMutable() {
  623.         if (!emails_.isModifiable()) {
  624.           emails_ = new com.google.protobuf.LazyStringArrayList(emails_);
  625.         }
  626.         bitField0_ |= 0x00000004;
  627.       }
  628.       /**
  629.        * repeated string emails = 3;
  630.        * @return A list containing the emails.
  631.        */
  632.       public com.google.protobuf.ProtocolStringList
  633.           getEmailsList() {
  634.         emails_.makeImmutable();
  635.         return emails_;
  636.       }
  637.       /**
  638.        * repeated string emails = 3;
  639.        * @return The count of emails.
  640.        */
  641.       public int getEmailsCount() {
  642.         return emails_.size();
  643.       }
  644.       /**
  645.        * repeated string emails = 3;
  646.        * @param index The index of the element to return.
  647.        * @return The emails at the given index.
  648.        */
  649.       public java.lang.String getEmails(int index) {
  650.         return emails_.get(index);
  651.       }
  652.       /**
  653.        * repeated string emails = 3;
  654.        * @param index The index of the value to return.
  655.        * @return The bytes of the emails at the given index.
  656.        */
  657.       public com.google.protobuf.ByteString
  658.           getEmailsBytes(int index) {
  659.         return emails_.getByteString(index);
  660.       }
  661.       /**
  662.        * repeated string emails = 3;
  663.        * @param index The index to set the value at.
  664.        * @param value The emails to set.
  665.        * @return This builder for chaining.
  666.        */
  667.       public Builder setEmails(
  668.           int index, java.lang.String value) {
  669.         if (value == null) { throw new NullPointerException(); }
  670.         ensureEmailsIsMutable();
  671.         emails_.set(index, value);
  672.         bitField0_ |= 0x00000004;
  673.         onChanged();
  674.         return this;
  675.       }
  676.       /**
  677.        * repeated string emails = 3;
  678.        * @param value The emails to add.
  679.        * @return This builder for chaining.
  680.        */
  681.       public Builder addEmails(
  682.           java.lang.String value) {
  683.         if (value == null) { throw new NullPointerException(); }
  684.         ensureEmailsIsMutable();
  685.         emails_.add(value);
  686.         bitField0_ |= 0x00000004;
  687.         onChanged();
  688.         return this;
  689.       }
  690.       /**
  691.        * repeated string emails = 3;
  692.        * @param values The emails to add.
  693.        * @return This builder for chaining.
  694.        */
  695.       public Builder addAllEmails(
  696.           java.lang.Iterable<java.lang.String> values) {
  697.         ensureEmailsIsMutable();
  698.         com.google.protobuf.AbstractMessageLite.Builder.addAll(
  699.             values, emails_);
  700.         bitField0_ |= 0x00000004;
  701.         onChanged();
  702.         return this;
  703.       }
  704.       /**
  705.        * repeated string emails = 3;
  706.        * @return This builder for chaining.
  707.        */
  708.       public Builder clearEmails() {
  709.         emails_ =
  710.           com.google.protobuf.LazyStringArrayList.emptyList();
  711.         bitField0_ = (bitField0_ & ~0x00000004);;
  712.         onChanged();
  713.         return this;
  714.       }
  715.       /**
  716.        * repeated string emails = 3;
  717.        * @param value The bytes of the emails to add.
  718.        * @return This builder for chaining.
  719.        */
  720.       public Builder addEmailsBytes(
  721.           com.google.protobuf.ByteString value) {
  722.         if (value == null) { throw new NullPointerException(); }
  723.         checkByteStringIsUtf8(value);
  724.         ensureEmailsIsMutable();
  725.         emails_.add(value);
  726.         bitField0_ |= 0x00000004;
  727.         onChanged();
  728.         return this;
  729.       }
  730.       // @@protoc_insertion_point(builder_scope:Person)
  731.     }
  732.     // @@protoc_insertion_point(class_scope:Person)
  733.     private static final PersonOuterClass.Person DEFAULT_INSTANCE;
  734.     static {
  735.       DEFAULT_INSTANCE = new PersonOuterClass.Person();
  736.     }
  737.     public static PersonOuterClass.Person getDefaultInstance() {
  738.       return DEFAULT_INSTANCE;
  739.     }
  740.     private static final com.google.protobuf.Parser<Person>
  741.         PARSER = new com.google.protobuf.AbstractParser<Person>() {
  742.       @java.lang.Override
  743.       public Person parsePartialFrom(
  744.           com.google.protobuf.CodedInputStream input,
  745.           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
  746.           throws com.google.protobuf.InvalidProtocolBufferException {
  747.         Builder builder = newBuilder();
  748.         try {
  749.           builder.mergeFrom(input, extensionRegistry);
  750.         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
  751.           throw e.setUnfinishedMessage(builder.buildPartial());
  752.         } catch (com.google.protobuf.UninitializedMessageException e) {
  753.           throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
  754.         } catch (java.io.IOException e) {
  755.           throw new com.google.protobuf.InvalidProtocolBufferException(e)
  756.               .setUnfinishedMessage(builder.buildPartial());
  757.         }
  758.         return builder.buildPartial();
  759.       }
  760.     };
  761.     public static com.google.protobuf.Parser<Person> parser() {
  762.       return PARSER;
  763.     }
  764.     @java.lang.Override
  765.     public com.google.protobuf.Parser<Person> getParserForType() {
  766.       return PARSER;
  767.     }
  768.     @java.lang.Override
  769.     public PersonOuterClass.Person getDefaultInstanceForType() {
  770.       return DEFAULT_INSTANCE;
  771.     }
  772.   }
  773.   private static final com.google.protobuf.Descriptors.Descriptor
  774.     internal_static_Person_descriptor;
  775.   private static final
  776.     com.google.protobuf.GeneratedMessage.FieldAccessorTable
  777.       internal_static_Person_fieldAccessorTable;
  778.   public static com.google.protobuf.Descriptors.FileDescriptor
  779.       getDescriptor() {
  780.     return descriptor;
  781.   }
  782.   private static  com.google.protobuf.Descriptors.FileDescriptor
  783.       descriptor;
  784.   static {
  785.     java.lang.String[] descriptorData = {
  786.       "\n\014person.proto"2\n\006Person\022\014\n\004name\030\001 \001(\t\022\n" +
  787.       "\n\002id\030\002 \001(\005\022\016\n\006emails\030\003 \003(\tb\006proto3"
  788.     };
  789.     descriptor = com.google.protobuf.Descriptors.FileDescriptor
  790.       .internalBuildGeneratedFileFrom(descriptorData,
  791.         new com.google.protobuf.Descriptors.FileDescriptor[] {
  792.         });
  793.     internal_static_Person_descriptor =
  794.       getDescriptor().getMessageTypes().get(0);
  795.     internal_static_Person_fieldAccessorTable = new
  796.       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
  797.         internal_static_Person_descriptor,
  798.         new java.lang.String[] { "Name", "Id", "Emails", });
  799.     descriptor.resolveAllFeaturesImmutable();
  800.   }
  801.   // @@protoc_insertion_point(outer_class_scope)
  802. }
复制代码
执行

从上面编译出来的文件中可以找到这行注释// Protobuf Java Version: 4.31.1,表示protobuf对应java依赖的版本。

  • 在pom.xml中引入依赖
  1. <dependency>
  2.   <groupId>com.google.protobuf</groupId>
  3.   protobuf-java</artifactId>
  4.   <version>4.31.1</version>
  5. </dependency>
复制代码

  • java测试代码
  1. public static void main(String[] args) throws InvalidProtocolBufferException {
  2.     // 构造对象
  3.     PersonOuterClass.Person person = PersonOuterClass.Person.newBuilder()
  4.     .setName("Alice")
  5.     .setId(123)
  6.     .addEmails("alice@example.com")
  7.     .build();
  8.     // 序列化为字节数组
  9.     byte[] bytes = person.toByteArray();
  10.     // 反序列化
  11.     PersonOuterClass.Person parsedPerson = PersonOuterClass.Person.parseFrom(bytes);
  12.     System.out.println(parsedPerson.getName());
  13.     System.out.println(parsedPerson.getId());
  14.     System.out.println(parsedPerson.getEmails(0));
  15. }
复制代码

  • 执行结果
  1. Alice
  2. 123
  3. alice@example.com
复制代码
性能测试

protobuf和json的性能对比

此处对比protobuf、hutool的json工具类、jackson的性能

  • 引入依赖
  1. <dependency>
  2.   <groupId>org.junit.jupiter</groupId>
  3.   junit-jupiter-api</artifactId>
  4.   <version>5.8.2</version>
  5. </dependency>
  6. <dependency>
  7.   <groupId>org.openjdk.jmh</groupId>
  8.   jmh-core</artifactId>
  9.   <version>1.37</version>
  10. </dependency>
  11. <dependency>
  12.   <groupId>org.openjdk.jmh</groupId>
  13.   jmh-generator-annprocess</artifactId>
  14.   <version>1.37</version>
  15.   <scope>provided</scope>
  16. </dependency>
  17. <dependency>
  18.   <groupId>com.fasterxml.jackson.core</groupId>
  19.   jackson-databind</artifactId>
  20.   <version>2.15.2</version>
  21. </dependency>
  22. <dependency>
  23.   <groupId>com.fasterxml.jackson.core</groupId>
  24.   jackson-core</artifactId>
  25.   <version>2.15.2</version>
  26. </dependency>
  27. <dependency>
  28.   <groupId>com.fasterxml.jackson.core</groupId>
  29.   jackson-annotations</artifactId>
  30.   <version>2.15.2</version>
  31. </dependency>
  32. <dependency>
  33.   <groupId>cn.hutool</groupId>
  34.   hutool-all</artifactId>
  35.   <version>5.8.27</version>
  36. </dependency>
复制代码

  • 测试的pojo类
  1. public class PersonJson {
  2.     private String name;
  3.     private int id;
  4.     private String[] emails;
  5.     public String getName() {
  6.         return name;
  7.     }
  8.     public void setName(String name) {
  9.         this.name = name;
  10.     }
  11.     public int getId() {
  12.         return id;
  13.     }
  14.     public void setId(int id) {
  15.         this.id = id;
  16.     }
  17.     public String[] getEmails() {
  18.         return emails;
  19.     }
  20.     public void setEmails(String[] emails) {
  21.         this.emails = emails;
  22.     }
  23. }
复制代码

  • 测试代码
  1. package protobuf;
  2. import cn.hutool.json.JSONUtil;
  3. import com.fasterxml.jackson.core.JsonProcessingException;
  4. import com.fasterxml.jackson.databind.ObjectMapper;
  5. import org.openjdk.jmh.annotations.*;
  6. import java.io.IOException;
  7. @Warmup(iterations = 2, time = 1)
  8. @Measurement(iterations = 2, time = 1)
  9. @Fork(2)
  10. @State(Scope.Thread)
  11. public class ProtobufBenchmark {
  12.     private PersonOuterClass.Person person;
  13.     private byte[] serializedData;
  14.     private String jsonStr;
  15.     private PersonJson personJson;
  16.     private ObjectMapper objectMapper = new ObjectMapper();
  17.     @Setup
  18.     public void setup() {
  19.         person = PersonOuterClass.Person.newBuilder()
  20.                 .setName("Charlie")
  21.                 .setId(789)
  22.                 .addEmails("charlie@example.com")
  23.                 .build();
  24.         serializedData = person.toByteArray();
  25.         personJson = new PersonJson();
  26.         personJson.setName("Charlie");
  27.         personJson.setId(789);
  28.         personJson.setEmails(new String[]{"charlie@example.com"});
  29.         jsonStr = JSONUtil.toJsonStr(personJson);
  30.     }
  31.     /**
  32.      * 测试protobuf序列化
  33.      *
  34.      * @return
  35.      */
  36.     @Benchmark
  37.     public byte[] testSerialize() {
  38.         return person.toByteArray();
  39.     }
  40.     /**
  41.      * 测试protobuf反序列化
  42.      *
  43.      * @return
  44.      * @throws Exception
  45.      */
  46.     @Benchmark
  47.     public PersonOuterClass.Person testDeserialize() throws Exception {
  48.         return PersonOuterClass.Person.parseFrom(serializedData);
  49.     }
  50.     /**
  51.      * 测试hutool-json序列化
  52.      *
  53.      * @return
  54.      */
  55.     @Benchmark
  56.     public String testJsonSerialize() {
  57.         return JSONUtil.toJsonStr(personJson);
  58.     }
  59.     /**
  60.      * 测试hutool-json反序列化
  61.      *
  62.      * @return
  63.      */
  64.     @Benchmark
  65.     public PersonJson testJsonDeserialize() {
  66.         return JSONUtil.toBean(jsonStr, PersonJson.class);
  67.     }
  68.     /**
  69.      * 测试Jackson序列化
  70.      *
  71.      * @return
  72.      * @throws JsonProcessingException
  73.      */
  74.     @Benchmark
  75.     public String testJacksonSerialize() throws JsonProcessingException {
  76.         return objectMapper.writeValueAsString(personJson);
  77.     }
  78.     /**
  79.      * 测试Jackson反序列化
  80.      *
  81.      * @return
  82.      * @throws Exception
  83.      */
  84.     @Benchmark
  85.     public PersonJson testJacksonDeserialize() throws Exception {
  86.         return objectMapper.readValue(jsonStr, PersonJson.class);
  87.     }
  88. }
复制代码
运行结果
  1. Benchmark                                  Mode  Cnt         Score         Error  Units
  2. ProtobufBenchmark.testSerialize           thrpt    4  23652174.844 ± 1801935.493  ops/s
  3. ProtobufBenchmark.testDeserialize         thrpt    4   7830878.513 ± 2204277.060  ops/s
  4. ProtobufBenchmark.testJacksonSerialize    thrpt    4   5737731.097 ±  975288.754  ops/s
  5. ProtobufBenchmark.testJacksonDeserialize  thrpt    4   2806124.511 ±  396224.766  ops/s
  6. ProtobufBenchmark.testJsonSerialize       thrpt    4    256885.571 ±   42109.112  ops/s
  7. ProtobufBenchmark.testJsonDeserialize     thrpt    4    289602.156 ±   78181.194  ops/s
复制代码

  • protobuf序列化性能是jackson的4倍,反序列化性能也将近3倍
  • hutool的json性能就比较差了,所以实际项目中若要使用json,推荐使用jackson
小结

本文介绍了protobuf从安装到使用的全过程,并提供了相应的代码示例。读者可以通过直接运行代码示例直观的学习到protobuf如何使用。最后测试和对比了protobuf、json序列化和反序列化的性能。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册