简介:
最近接手了一个数据量较大的项目,项目整体主要以kafka分发传递数据,一部分是json格式数据,但是大部分都用到了proto格式数据,之前也没解析过这种格式的数据,搜了半天的文档,写了个demo总结了下
提示:不知道protobuf的可以先百度一下
首先搭建基础环境:
1.先下载一个proto文件编译器
可以参考这篇文章:protoc下载
然后记得配置环境变量,或者不配置也行,需要把编译器放在和proto文件同一目录下
2.新建一个项目,我这里使用的是springboot,具体maven依赖看下图
如果自己项目没有导入junit的依赖,需要再导入下
准备proto文件、执行protoc编译器生成java类
1.先准备proto文件
这里准备一个学生信息proto文件,大致是这样的结构
proto文件内容如下
// proto版本,可以不指定,默认proto2
syntax = "proto2";
option java_outer_classname = "StudentProtoBo";
// 枚举,用户性别,可作为类型被message引用,类似我们在一个对象中定义性别的枚举属性(变量)
enum Sex {
// 男
MAN = 1;
// 女
WOMAN = 2;
}
// 成绩,可能有多科,我们这里假定有java、c、python三门课程
message Score {
// 课程名称
optional string course_name = 1;
// 课程编号
optional string course_code = 2;
// 成绩
optional float score = 3;
}
// 学生信息,使用Sex枚举和Score作为字段
message Student {
// 这里使用int64,实际项目开发中这些id很可能都是雪花算法生成的,差不多19位整数
optional int64 stu_id = 1;
// 用户名称
optional string name = 2;
// 【使用Sex枚举值作为性别】
optional Sex sex = 3;
// 【使用Score作为多科成绩】
repeated Score scores = 4;
}
2.执行protoc编译proto文件,生成java类
先cd到resource目录下,然后执行protoc --java_out=./ ./student.proto,然后会生成java类
然后移动到bo文件夹下,记得指定package
编写单元测试,测试基本流程
1.在test目录下创建一个测试类,新增test方法,记得用junit的@Test注解标记
然后执行单元测试的测试方法,这里学生名称需要用student.getName方法获取,否则是这样的数据
最后单元测试代码如下,可直接运行
package com.ddm.example.protodemo;
import com.ddm.example.protodemo.bo.StudentProtoBo;
import com.google.protobuf.InvalidProtocolBufferException;
import org.junit.jupiter.api.Test;
/**
* <Description> <br>
*
* @author Your name <br>
* @version 1.0 <br>
* @date 2022/03/17 <br>
*/
public class TestProto {
@Test
public void test() {
// ------------------- 数据的发送方 ---------------------------
// 初始化学生对象,设置属性
StudentProtoBo.Student.Builder stuBuilder = StudentProtoBo.Student.newBuilder();
// 设置学生名称
stuBuilder.setName("张三");
// 设置学生id
stuBuilder.setStuId(1407399920872418600L);
// 性别
stuBuilder.setSex(StudentProtoBo.Sex.MAN);
// java成绩
StudentProtoBo.Score.Builder javaScoreBuilder = StudentProtoBo.Score.newBuilder();
javaScoreBuilder.setCourseCode("1-03");
javaScoreBuilder.setCourseName("Java");
javaScoreBuilder.setScore(60.5f);
// c成绩
StudentProtoBo.Score.Builder cScoreBuilder = StudentProtoBo.Score.newBuilder();
cScoreBuilder.setCourseCode("1-02");
cScoreBuilder.setCourseName("C");
cScoreBuilder.setScore(70.0f);
// python成绩
StudentProtoBo.Score.Builder pythonScoreBuilder = StudentProtoBo.Score.newBuilder();
pythonScoreBuilder.setCourseCode("1-01");
pythonScoreBuilder.setCourseName("Python");
pythonScoreBuilder.setScore(65.0f);
// 添加到学生的成绩列表中
stuBuilder.addScores(javaScoreBuilder.build());
stuBuilder.addScores(cScoreBuilder.build());
stuBuilder.addScores(pythonScoreBuilder.build());
// build,然后转为字节流即可发送给需要数据的业务方
byte[] stuBytes = stuBuilder.build().toByteArray();
String s = new String(stuBytes);
System.out.println(s);
// -------------------------------------------------- 数据的消费方( 解析数据 ) ------------------------------------
// 使用StudentOuterClass的parse方法
try {
StudentProtoBo.Student student = StudentProtoBo.Student.parseFrom(stuBytes);
System.out.println();
System.out.println();
System.out.println("解析后数据:");
System.out.println(student.toString());
System.out.println("学生名字:" + student.getName());
} catch (InvalidProtocolBufferException e) {
// 这里直接打印错误日志了,实际开发中可以使用log日志
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
一个简单的小案例,入门protobuf,实际在项目中的用法要视需求而定