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

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 文件中添加如下依赖:

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 的话就是不需要),MyRequestHeader 是消息结构。

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

css 复制代码
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举个🌰

java 复制代码
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 完整代码

ini 复制代码
//协议版本
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;
}
相关推荐
paopaokaka_luck12 分钟前
[371]基于springboot的高校实习管理系统
java·spring boot·后端
捂月1 小时前
Spring Boot 深度解析:快速构建高效、现代化的 Web 应用程序
前端·spring boot·后端
瓜牛_gn2 小时前
依赖注入注解
java·后端·spring
Estar.Lee2 小时前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
喜欢猪猪2 小时前
Django:从入门到精通
后端·python·django
一个小坑货2 小时前
Cargo Rust 的包管理器
开发语言·后端·rust
bluebonnet272 小时前
【Rust练习】22.HashMap
开发语言·后端·rust
uhakadotcom2 小时前
如何实现一个基于CLI终端的AI 聊天机器人?
后端
Iced_Sheep3 小时前
干掉 if else 之策略模式
后端·设计模式
XINGTECODE3 小时前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang