Protocol Buffer序列化/反序列化---初体验(java版)

今天闲遐时学习了

Protocol Buffer

在网上看到了许多资料,其中不泛精品,想要详细了解的请看文章结尾的友情链接,我这里就做加深印象,快速入门的一个完整的demo,仅此而已.

学完你可以得到什么:

  1. 可以使用protoc工具序列化类,反序列化类
  2. 基于java语言的对protoc工具的基本使用
  3. 基本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

posted @ 2019-02-25 18:09  孤燕南飞  阅读(1727)  评论(0编辑  收藏  举报