今天閑遐時學習了
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
