Protobuf序列化

发布于 2021-06-13  695 次阅读


Protobuf是Googel发布的开源项目,全称Google Protobuf Buffers,是一种轻便高效的结构化数据存储格式,可以序列化,它适用于做数据的存储或RPC[远程过程调用]数据交互格式
 
Protobuf是以message的方式来管理数据的,它支持跨平台,跨语言,即客户端和服务器可以是不同的语言编写的(它支持大多数语言,例如:C++,C#,java,python等)
 
Protobuf的出现改变了数据交互的格式,以前我们是http+json的方式传输数据,现在可以用tcp+protobuf的形式进行数据交互,tcp+protobuf它的效率会更高
protobuf的基本使用:
  1. 本身它的相比于传统的Java序列化它是高性能,高可靠的
  2. 使用protobuf编译器能自动生成代码,Protobuf是将类的定义使用以.proto文件进行描述,注:在idea中编写.proto文件时,需要下载.ptotot编写插件,可以让语法高亮
  3. 通过proto.exe编译器根据.proto自动生成.java文件(不同的语言生成不同语言的文件,它本身为跨语言而产生的)

protobuf编译工具 链接地址为:https://github.com/protocolbuffers/protobuf/releases 

选择 https://github.com/protocolbuffers/protobuf/releases/download/v3.9.0/protoc-3.9.0-win64.zip,对应的版本进行下载。

编写Protobuf程序的步骤:

  1)导入maven依赖
<dependency>
<groupId>com.google.protobuf</groupId
<artifactId>protobuf-java</artifactId>
<version>3.17.2</version>
</dependency>
  2)新建以.proto文件编写protobuf程序
  注:第一次新建的时候会提示下载ptotot插件,下载进行,直接写代码有提示
Protobuf数据类型与java数据类型的对应关系图:

案例:用protobuf序列化替代原先的序列化
要求:
  1. 客户端可以发送一个wql Pojo对象到服务器(通过ProtoEncoder进行编码)
  2. 服务器端接收wql Pojo对象(通过ProtoDncoder进行解码),并显示
①Protobuf文件编写 
syntax = "proto3";//版本号

option java_outer_classname = "wql";//生成的外部java类名

//protobuf使用message管理数据

message wql_fq{

//会在wql外部类中生成一个内部类,它是真正发送的POJO对象

//在wql_fq类中有一个属性名字为id,类型为int32(这是protobuf自带的类型,跟java类型有对应关系,int32对应java的int)

//1表示属性序号,不表示值

int32 id = 1;

string name=2;

}
② 通过proto.exe编译器把.proto文件编译成.java文件
命令:proto.exe java-out = . 文件名
③编写netty服务端和客户端,将protobuf序列化替换原有序列化
不全部上代码了,只把关键部分写出来
在client和server中的Pipeline中分别加入ProtoEncoder(编码器)和ProtoDecoder(解码器)
客户端:
//加入handler处理器

socketChannel.pipeline().addLast(new handlerclient_netty());

//加入Protobuf编码器

socketChannel.pipeline().addLast("encode",new ProtobufEncoder());
服务端:
//添加自定义处理器

socketChannel.pipeline().addLast(new handler_netty());

//添加Protobuf解码器,参数需要指定对那种对象进行解码

socketChannel.pipeline().addLast("decode",new ProtobufDecoder(wql.wql_fq.getDefaultInstance()));

客户端处理器(Handler):

//获取并设置Protobuf的对象实例

//设置ID值为4,name值为晴天,并将对象返回

wql.wql_fq build = wql.wql_fq.newBuilder().setId(4).setName("晴天").build();

//将对象发送给服务器端

ctx.writeAndFlush(build);

服务端处理器:

//读取从客户端发送的数据wql.wql_fq

wql.wql_fq build = (wql.wql_fq)msg;

//读取客户端发送的数据

System.out.println("ID:"+build.getId()+"name:"+build.getName());


路漫漫其修远兮,吾将上下而求索