Protocol Buffer序列化/反序列化---初体验(java版)
今天闲遐时学习了
Protocol Buffer
在网上看到了许多资料,其中不泛精品,想要详细了解的请看文章结尾的友情链接,我这里就做加深印象,快速入门的一个完整的demo,仅此而已.
学完你可以得到什么:
- 可以使用protoc工具序列化类,反序列化类
- 基于java语言的对protoc工具的基本使用
- 基本protoc的基础api使用
首先我们需要下载官方的编译工具,
FQ版: 官方文档
不翻版:我的仓库
整体流程:序列化一个实体类,在反序列出来得到结果:
先放出结果来瞅瞅:
可以看到数据压缩了将近一半多,so GOOD!!!
言归正传:
首先我们
新建一个proto文件,定义基本的数据格式
syntax = "proto2"; option java_outer_classname="PersonProtoBuf"; message Person{ optional int32 id = 1; optional int32 age = 2; optional string name= 3; optional bool is_sex= 4; } message Class{ optional int32 grade_num = 1; optional int32 class_num = 2; optional Person head_teacher = 3; repeated Person students = 4[packed=true]; }
* 第一句确定是语法版本 * 其二是指定生成的class * 还可以指定包名 * 主体: * message Person{...} * 主要实体编写区域 * 其中: * optional:非必需参数 * repeated:可以重复存储一个字段,其中是待顺序的存取 * required:必要参数 * * 结构体、类,统一定义为 message,实际上是嵌套类 * * int32,string,bool 数据格式 * 1,2,3,4 表示数据元素的唯一编号 * * * 还可以定义: * enum xx //枚举定义 * { * XXX = 0; * ... * } * * struct SS{ //结构体定义 * required int s1; * required int s2; * } * * 具体需要FQ查看官网文档: https://developers.google.com/protocol-buffers/docs/javatutorial * 接下来就需要:使用java程序进行压缩,模拟解压.
这个protoc的工具加不加环境变量随便,使用命令(我这里是加了环境变量):
protoc --java_out=./ ./****.proto文件
其中第一个./是将生成的java文件放在本目录下,其二个则是在找到这个proto文件,
这里还需要编写其proto文件...
执行结果:
我们现在创建java项目,添加protocol 的jar依赖
<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.7.0-rc1</version> </dependency>
基本结构
public class ServiceSchool { private PClass pClass = null; /** * 初始化班级 */ @Before public void initClass(){ //设置教师类 Person teacher = new Teacher(1,30,"王老师",false); //设置学生类 一个班级50人 List<Person> allStudents = new ArrayList<>(); for(int i = 0; i < 50; i++) { Person student = null; if(i % 2 == 0) { student = new Student(i + 1000, (int) (Math.random() * 20), "学生" + i + "号", true); }else{ student = new Student(i + 1000, (int) (Math.random() * 20), "学生" + i + "号", false); } allStudents.add(student); } pClass = new PClass(7,3,teacher,allStudents); } /** * 模拟传输的数据字节数组 */ private byte[] pipeByArray = null; /** * 压缩 */ @Test public void compression() throws InvalidProtocolBufferException { // 原数据 System.out.println("原数据的长度: "+pClass.toString().length()); //压缩后 School.Class.Builder pClassCom = setBuilder(pClass); School.Class build = pClassCom.build(); pipeByArray = build.toByteArray(); System.out.println("压缩后数据长度:"+pipeByArray.length); } /** * 模拟解压 */ @After public void decompression() throws InvalidProtocolBufferException { School.Class.Builder aClass = School.Class.parseFrom(pipeByArray).toBuilder(); //// 解压 int classNum = aClass.getClassNum(); int gradeNum = aClass.getGradeNum(); School.Person headTeacher = aClass.getHeadTeacher(); List<School.Person> studentsList = aClass.getStudentsList(); System.out.println("教师:"+headTeacher.getId() +headTeacher.getName() +headTeacher.getAge() +headTeacher.getIsSex()); for(School.Person p : studentsList){ System.out.println(p.getName()+"-"+p.getId()+"-"+p.getIsSex()+"-"+p.getAge()); } } /** * 添加数据 * * @param pClass * @return */ private School.Class.Builder setBuilder(PClass pClass){ School.Person.Builder person = School.Person.newBuilder(); //教师类 Person headTeacher = pClass.getHeadTeacher(); //添加教师类 person.setName(headTeacher.getName()); person.setAge(headTeacher.getAge()); person.setIsSex(headTeacher.isSex()); person.setId(headTeacher.getId()); //教室类 School.Class.Builder sClass = School.Class.newBuilder(); sClass.setGradeNum(pClass.getGradeNum()); sClass.setClassNum(pClass.getClassNum()); sClass.setHeadTeacher(person); //遍历学生 for(int i = 0; i < pClass.getStudents().size();i++){ Person p = pClass.getStudents().get(i); person.setName(p.getName()); person.setAge(p.getAge()); person.setIsSex(p.isSex()); person.setId(p.getId()); sClass.addStudents(i,person); } return sClass; } }
发现其中数据量越少,压缩后会更小基本上都是1/3原来的体积,下一次准备使用这个协议做rpc了,哈哈
参考网站:
https://www.ibm.com/developerworks/cn/linux/l-cn-gpb/
https://worktile.com/tech/share/prototol-buffers
平凡是我的一个标签