一、简介
Protocal Buffers(简称protobuf)是谷歌的一项技术,用于结构化的数据序列化、反序列化。
Protocol Buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。
Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。
你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序
与JSON相比
protobuf的效率高,不过protobuf生成的是字节码,可读性相比之略差
Protobuf不仅仅是一种消息格式,它还是一组用于定义和交换这些消息的规则和工具。 谷歌是这个协议的创造者,已开源,并为常用的编程语言提供生成代码的工具,
如JavaScript,Java,PHP,C#,Ruby,Objective C,Python,C ++和Go。 除此之外,Protobuf具有比JSON更多的数据类型,如枚举和方法,并且还大量用于RPC(远程过程调用)
参考资料
名称 | 地址 |
---|---|
protobuf 编译器 | Releases · protocolbuffers/protobuf · GitHub |
Protobuf 语法指南 | [译]Protobuf 语法指南 |
二、protobuf 环境配置
1.下载编译器
选择自己需要的版本下载即可,我这里下载的是win64 3.15.3,下载之后进行解压
2.配置环境变量
path 系统变量中增加配置,也就是你的解压文件位置
3.检查是否配置成功
cmd 之后,输入
protoc |
查看版本
protoc --version |
这样我们就可以在命令行去生成 proto 文件了
二、idea 中使用 protobuf
1.idea 安装 protobuf 相关插件
任意安装以下插件即可,安装之后重启 idea
一个是根据 .proto 文件来生成 proto 对象
一个是使得 idea 支持我们的 proto 语法,例如关键词高亮等功能
2.写一个简单的 proto
//使用 proto3 语法 ,未指定则使用proto2 syntax = "proto3"; //生成 proto 文件所在包路径 package com.wxw.notes.protobuf.proto; //生成 proto 文件所在包路径 option java_package = "com.wxw.notes.protobuf.proto"; //生成 proto 文件名 option java_outer_classname="DemoProto"; message Demo{ //自身属性 int32 id = 1; string code = 2; string name = 3; } |
如果发现有这种红色标识,千万不要以为是我们 Java 里面的异常错误,这只是 proto 的语法高亮
3.生成 proto 对象
选中我们新建的.proto 文件,右键,选择框中的选项就可以生成了
生成后的 proto 文件如下
三、protobuf方法使用
1.序列化和反序列化
package com.wxw.notes.protobuf.test; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.MessageOrBuilder; import com.google.protobuf.TextFormat; import com.google.protobuf.util.JsonFormat; import com.wxw.notes.protobuf.proto.DemoProto; import java.util.Arrays; public class SimpleTestMain { public static void main(String[] args) { //初始化数据 DemoProto.Demo.Builder demo = DemoProto.Demo.newBuilder(); demo.setId(1) .setCode("001") .setName("张三") .build(); //序列化 DemoProto.Demo build = demo.build(); //转换成字节数组 byte[] s = build.toByteArray(); System.out.println("protobuf数据bytes[]:" + Arrays.toString(s)); System.out.println("protobuf序列化大小: " + s.length); DemoProto.Demo demo1 = null; String jsonObject = null; try { //反序列化 demo1 = DemoProto.Demo.parseFrom(s); //转 json jsonObject = JsonFormat.printer().print(demo1); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } System.out.println("Json格式化结果:\n" + jsonObject); System.out.println("Json格式化数据大小: " + jsonObject.getBytes().length); } |
2.protobuf 和 JSON 互相转换
引入依赖
com.google.protobufprotobuf-java-util3.7.1 |
代码实现
public class ProtoJsonUtils { public static String toJson(Message sourceMessage) throws IOException { String json = JsonFormat.printer().print(sourceMessage); return json; } public static Message toProtoBean(Message.Builder targetBuilder, String json) throws IOException { JsonFormat.parser().merge(json, targetBuilder); return targetBuilder.build(); } } |
对于一般的数据类型,如int,double,float,long,string都能够按照理想的方式进行转化。对于protobuf中的enum类型字段,会被按照enum的名称转化为string。对于bytes类型的字段,则会转化为utf8类型的字符串
3.protobuf 与 Java 对象互转
引入依赖
<!-- protocol buffer support --> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>${protobuf.version}</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-all</artifactId> <version>${grpc.version}</version> </dependency> |
代码实现
public class ProtobufBeanUtil { private ProtobufBeanUtil(){ } /** * 将ProtoBean对象转化为POJO对象 * * @param destPojoClass 目标POJO对象的类类型 * @param sourceMessage 含有数据的ProtoBean对象实例 * @param <PojoType> 目标POJO对象的类类型范型 * @return * @throws IOException */ public static <PojoType> PojoType toPojoBean(@NotNull Class<PojoType> destPojoClass, @NotNull Message sourceMessage) throws IOException { String json = JsonFormat.printer().print(sourceMessage); return new Gson().fromJson(json, destPojoClass); } /** * 将POJO对象转化为ProtoBean对象 * * @param destBuilder 目标Message对象的Builder类 * @param sourcePojoBean 含有数据的POJO对象 * @return * @throws IOException */ public static void toProtoBean(@NotNull Message.Builder destBuilder, @NotNull Object sourcePojoBean) throws IOException { String json = new Gson().toJson(sourcePojoBean); JsonFormat.parser().merge(json, destBuilder); } |