protoBuf的学习
2.mac环境安装
brew命令安装下载
brew install protobuf
查看安装目录
which protoc
配置环境变量
sudo vi ~/.bash_profile
export PROTOC=/usr/local/bin/protoc
source ~/.bash_profile
查看版本
protoc --version
3.在java中简单使用
使用Protoc生成java类
首先在项目中创建一个demo.proto
文件,选择txt文件就行了
//使用 proto3 语法 ,未指定则使用proto2
syntax = "proto3";
//生成 proto 文件所在包路径
package com.wl.protobuf;
//生成 proto 文件所在包路径
option java_package = "com.wl.protobuf";
//生成 proto 文件名
option java_outer_classname="DemoProto";
message Demo{
//自身属性
int32 id = 1;
string code = 2;
string name = 3;
}
然后打开项目所在的控制台输入以下指令
protoc --java_out=src/main/java src/main/resources/demo.proto
--java_out=src/main/java
就是生成的java文件的路径src/main/resources/demo.proto
是 proto文件的路径protoc
是protobuf的指令
可以看到生成了一个DemoProto.java
文件,这个类可以帮我们生成序列化的对象和反序列化
在idea中安装插件 Protobuf Generator
和Protocol Buffer Editor
可以让idea识别到 .proto
文件
下载完成后找到 tools
修改规则
然后可以快速生成DemoProto.java
文件
序列化和反序列化
在得到 Protoc生成的java类以后,可以使用这个DemoProto.java
类进行序列化和反序列化
加入maven依赖
<!-- protobuf 支持 Java 核心包 这里最好对应自己系统上的版本-->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.19.4</version>
</dependency>
<!-- proto 与 Json 互转会用到-->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.15.3</version>
</dependency>
序列化和反序列化测试代码
package com.wl.protobuf;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import java.util.Arrays;
/**
* @author 没有梦想的java菜鸟
* @Date 创建时间:2022/5/17 下午6:06
* @qq 2315290571
* @Description protobuf 在java 的序列化和反序列化
*/
public class ProtoBufTest {
public static void main(String[] args) throws Exception {
// 初始化数据
DemoProto.Demo.Builder builder = DemoProto.Demo.newBuilder();
builder.setId(1)
.setCode("1001")
.setName("小明")
.build();
// 序列化
DemoProto.Demo build = builder.build();
// 转换成字节数组
byte[] contentBytes = build.toByteArray();
System.out.println("序列化后的数组内容:"+Arrays.toString(contentBytes));
System.out.println("序列化后的数组长度:"+contentBytes.length);
// 反序列化
DemoProto.Demo content = DemoProto.Demo.parseFrom(contentBytes);
// 转json
String jsonContent = JsonFormat.printer().print(content);
System.out.println("内容是:");
System.out.println(jsonContent);
}
}
运行结果如下:
4. java和protobuf数据类型的对应
字段规则
共有三种字段规则:
-
required:字段是必须且唯一的
-
optional:字段可以出现0次或多次,可选字段
-
repeate:字段可以任意次数出现,一般用于生成java的List集合
required
required int32 id = 1 [default = 123]
optional
optional string name = 1 [default = "张三"]
repeate
//list String
repeated string strList = 5;
//list 对象
repeated Role roleList = 6;
字段编号
在消息定义中,每个字段都有唯一的一个标识符。[1,15]之内的标识号在编码的时候会占用一个字节。[16,2047]之内的标识号则占用2个字节。
字段类型
基本数据类型
复杂数据类型
创建一个名为test.proto
和Teacher.proto
的文件,然后使用 protoc
生成Java文件
test.proto
//使用 proto3 语法 ,未指定则使用proto2
syntax = "proto3";
//生成 proto 文件所在包路径
package com.wl.protobuf;
//生成 proto 文件所在包路径
option java_package = "com.wl.protobuf";
// 生成的文件名
option java_outer_classname = "ComplexProto";
// 引入外部文件
import "Teacher.proto";
// 创建一个User类
message User{
// 定义string,int类型的map集合
map<string, int32> intMap = 3;
// 定义string,Student类型的map集合
map<string, Student> stuMap = 2;
// 定义string 类型的list集合
repeated string list = 8;
// 引入外部的Teacher.proto的文件
repeated Teacher teacherList = 4;
}
// 定义Student对象
message Student{
string stuId = 1;
string stuName = 5;
string stuSchool = 6;
}
Teacher.proto
//使用 proto3 语法 ,未指定则使用proto2
syntax = "proto3";
//生成 proto 文件所在包路径
package com.wl.protobuf;
//生成 proto 文件所在包路径
option java_package = "com.wl.protobuf";
// 生成的文件名
option java_outer_classname = "TeacherProto";
message Teacher{
string tId=1;
string tName=2;
string tSchool=3;
}
Test测试类
package com.wl.protobuf.complex;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
/**
* @author 没有梦想的java菜鸟
* @Date 创建时间:2022/5/18 下午12:18
* @qq 2315290571
* @Description 测试类
*/
public class Test {
public static void main(String[] args) throws InvalidProtocolBufferException {
// 赋值Student 对象
ComplexeProto.Student.Builder stuBuilder = ComplexeProto.Student.newBuilder();
ComplexeProto.Student student = stuBuilder.setStuId("1001")
.setStuName("小明")
.setStuSchool("北京大学")
.build();
ComplexeProto.Student student2 = stuBuilder.setStuId("1002")
.setStuName("小李")
.setStuSchool("上海大学")
.build();
// 赋值Teacher对象
TeacherProto.Teacher.Builder tBuilder = TeacherProto.Teacher.newBuilder();
TeacherProto.Teacher.Builder t1 = tBuilder.setTId("2001")
.setTName("胡老师")
.setTSchool("北京大学");
TeacherProto.Teacher.Builder t2 = tBuilder.setTId("2002")
.setTName("李老师")
.setTSchool("上海大学");
// 给User对象赋值
ComplexeProto.User.Builder userBuilder = ComplexeProto.User.newBuilder();
// 给intMap赋值
userBuilder.putIntMap("java", 1);
userBuilder.putIntMap("kotlin", 2);
// 给stuMap赋值
userBuilder.putStuMap("北京", student);
userBuilder.putStuMap("上海", student2);
// 给 String类型的list集合赋值
userBuilder.addList("A");
userBuilder.addList("B");
userBuilder.addList("C");
userBuilder.addList("D");
// 给teacherList赋值
userBuilder.addTeacherList(t1);
userBuilder.addTeacherList(t2);
// 序列化
ComplexeProto.User serialize = userBuilder.build();
// 转换成字节数组
byte[] bytes = serialize.toByteArray();
// 反序列化
ComplexeProto.User content = ComplexeProto.User.parseFrom(bytes);
// 转json
String json = JsonFormat.printer().print(content);
System.out.println(json);
}
}
输出结果