Protobuf详解及入门指南【保姆级教程】

目录

Protobuf概述

什么是Protobuf

为什么要使用Protobuf

Protobuf实战

环境配置

创建文件

解析/封装数据

附录

AQin.proto 完整代码


Protobuf概述

什么是Protobuf

Protobuf(Protocol Buffers)协议😉 Protobuf 是一种由 Google 开发的二进制序列化格式和相关的技术,它用于高效地序列化和反序列化结构化数据,通常用于网络通信、数据存储等场景

为什么要使用Protobuf

其实 Protobuf 在许多领域都得到了广泛应用,特别是在分布式系统、RPC(Remote Procedure Call)框架和数据存储中,它提供了一种高效、简洁和可扩展的方式来序列化和交换数据,Protobuf 的主要优点包括:

  1. 高效性:Protobuf 序列化后的二进制数据通常比其他序列化格式(比如超级常用的JSON)更小,并且序列化和反序列化的速度更快,这对于性能敏感的应用非常有益。
  2. 简洁性:Protobuf 使用一种定义消息格式的语法,它允许定义字段类型、顺序和规则(消息结构更加清晰和简洁)
  3. 版本兼容性:Protobuf 支持向前和向后兼容的版本控制,使得在消息格式发生变化时可以更容易地处理不同版本的通信。
  4. 语言无关性:Protobuf 定义的消息格式可以在多种编程语言中使用,这有助于跨语言的通信和数据交换(截至本文发布目前官方支持的有C++/C#/Dart/Go/Java/Kotlin/python)
  5. 自动生成代码:Protobuf 通常与相应的工具一起使用,可以自动生成代码,包括序列化/反序列化代码和相关的类(减少了手动编写代码的工作量,提高效率,后面的🌰里有保姆级操作指南)

Protobuf实战

环境配置

首先我们需要在 pom.xml 文件中添加如下依赖:

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.20.3</version>
</dependency>

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java-util</artifactId>
    <version>3.20.3</version>
</dependency>

接着如果你希望.proto文件可以被idea识别的话,就需要安装 Protobuf 插件(非必要)

创建文件

然后我们创建一个.proto文件,如下图(完整代码在文末附录)

其中 syntax = "proto3" 表示协议版本,option java_package = "com.aqin.protobuf" 表示生成的类所处的层级,option java_multiple_files = true 表示需要將生成的类拆分为多个(false 的话就是不需要),MyRequest 和 Header 是消息结构。

进入到文件📃AQin.proto所在目录下,执行如下代码:

protoc -I=./ --java_out=./ ./AQin.proto

参数说明:

  • -I 用于指定 .proto 文件所在的路径(也可以用-proto_path代替)
  • –java_out 用于指定生成的 java 文件的路径
  • ./AQin.proto 就是需要编译的.proto文件
  • 有一点需要注意的是这三个路径要使用相对路径就都使用相对路径,要使用绝对路径就都使用绝对路径(不要混着用),执行完成后,就会在指定的位置生成指定的文件,如下图

    然后我们就可以通过生成的Java类来对接收到的信息进行解析,或者封装数据进对象进行发送

    解析/封装数据

    常用API

  • newBuilder():用于创建Java类(通过.proto文件生成的)并返回该对象
  • setXXX():设置属性值
  • getXXX():获取属性值
  • byte[] toByteArray():用于序列化信息并返回一个字节数组
  • writeTo(OutputStream output): 序列化信息并写入一个输出流
  • parseFrom(byte[] data):解析传入的字节数组(一般用于接收数据)
  • parseFrom(InputStream input):解析传入的输入流(一般用于接收数据)
  • 那我们上面的AQin.proto举个🌰

    MyInfo myInfo = MyInfo.newBuilder().setName("Zhangsan");
    Body body = Body.newBuilder().setMyInfo(myInfo).build();
    ByteBuffer byteBuffer = ByteBuffer.allocate(body.toByteArray().length);
    body.writeTo(CodedOutputStream.newInstance(byteBuffer));
    //然后就可以发送了~~

    附录

    AQin.proto 完整代码

    //协议版本
    syntax = "proto3";
    //生成的类所处的层级
    option java_package = "com.aqin.protobuf";
    
    //是否需要將生成的类拆分为多个
    option java_multiple_files = true;
    
    // request
    message MyRequest{
      Header header = 1;
      Body body = 2;
    }
    
    //Header
    message Header {
      uint32  RequestId = 1;
      int64   Timestamp = 2;
    }
    
    //Body
    message Body {
      MyInfo Info = 1;  //消息
      ServiceResult serviceResult = 2;  //结果反馈
    }
    
    message MyInfo{
      string  name = 1;
      string  age = 2;
    }
    
    message ServiceResult{
      uint32 ErrorCode = 1;
      string ErrorMsg = 2;
    }

    作者:AQin1012

    物联沃分享整理
    物联沃-IOTWORD物联网 » Protobuf详解及入门指南【保姆级教程】

    发表回复