今天閑遐時學習了
Protocol Buffer
在網上看到了許多資料,其中不泛精品,想要詳細了解的請看文章結尾的友情鏈接,我這里就做加深印象,快速入門的一個完整的demo,僅此而已.
學完你可以得到什么:
- 可以使用protoc工具序列化類,反序列化類
- 基於java語言的對protoc工具的基本使用
- 基本protoc的基礎api使用
首先我們需要下載官方的編譯工具,
翻牆版: 官方文檔
不翻版:我的倉庫
整體流程:序列化一個實體類,在反序列出來得到結果:
先放出結果來瞅瞅:
可以看到數據壓縮了將近一半多,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; * } * * 具體需要翻牆查看官網文檔: 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