Protobuf入門

Protobuf是什么离赫?

官網(wǎng)解釋

Protobuf 是Google為序列化數(shù)據(jù)結(jié)構(gòu)提供的語言無關(guān),平臺無關(guān)旬盯,可擴(kuò)展的機(jī)制翎猛,它比XML更小更快更簡單。你可以定義你想定義的數(shù)據(jù)表示成結(jié)構(gòu)數(shù)據(jù)萨咳,然后你可以使用產(chǎn)生的代碼去寫或者從多種多樣的數(shù)據(jù)流中讀取你的結(jié)構(gòu)數(shù)據(jù)疫稿,并且在多種多樣的語言中使用。
Protocol buffers are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages.

下面我們編寫一個例子舀凛,例子的目標(biāo)是使用protobuf序列化和反序列化對象腾降。在本例子中我們使用java編寫碎绎,所以在這個過程用會引用到Maven構(gòu)建項(xiàng)目。

例子

步驟一:編寫proto文件

protobuf是一種跨語言的序列化/反序列化的工具奸晴,通過proto文件定義對象的數(shù)據(jù)結(jié)構(gòu)日麸,并依賴此proto文件進(jìn)行序列化和反序列化操作逮光。
新建PersonMsg.proto文件涕刚,詳細(xì)定義如下:

//定義使用的protobuf版本
syntax = "proto3"; //(1)

//定義所在的protobuf包空間
package  com.simple;//(2)

//生成的java類所在的包路徑
option java_package = "com.simple"; //(3)
//生成的java類的類名
option java_outer_classname = "PersonMsg"; //(4)

//聲明一個message類
message Person{ //(5)
      string name = 1;  //(6)
      int32 age =2;//(7)
      string email =3;//(8)
      string phoneNumber =4;//(9)
}

簡單解析一下:
(1)使用syntax關(guān)鍵字乙帮,定義要使用的protobuf版本,在這里我們使用proto3(注意:這個聲明必須在第一行驾茴。)
(2)這個是用來防止不同protobuf message 類型的命名沖突氢卡,在不同語言中package對生成代碼的影響也不一樣译秦,在java中,如果不顯式提供option java_package參數(shù)棋返,那么package所標(biāo)明的內(nèi)容就是生成java類所在的包路徑雷猪。詳細(xì)內(nèi)容請查看原文下的package說明:protobuf guide
(3)~(4)標(biāo)明java參數(shù)晰房,其他語言不需要提供此參數(shù)殊者。
如不提供java_package參數(shù),會使用上面聲明的package內(nèi)容作為生成的java類的包路徑猖吴。
如不提供java_outer_classname參數(shù)海蔽,會使用.proto文件的文件名作為生成java類的類名。
(5)這里聲明了一個名字是Person的message(注意:這里message的名字不能跟上面 java_outer_classname參數(shù)定義的名字一樣拗引。)
(6)~(9)在這里聲明了4個字段幌衣,聲明字段的格式是 "類型 字段名=標(biāo)號",在protobuf中哼凯,提供豐富的字段類型,在官網(wǎng)guide中可以查看proto類型對應(yīng)產(chǎn)生不同語言的類型(詳細(xì)查看Guide中的Scalar Value Types:protobuf guide)猎贴。message的標(biāo)號都是從1開始遞增家坎,標(biāo)號是不允許重復(fù)的虱疏。

步驟二:下載protobuf的編譯工具

編寫完proto文件,我們需要一個工具去編譯它对粪,所以我們需要下載protoc.exe装蓬。
下載方式:在官網(wǎng)中下載protoc-3.4.0-win32.zip(下載地址:protobuf 3.4下載鏈接),解壓可以看到在bin目錄下的protoc.exe儡遮,如下圖:

解壓后protoc.exe路徑

protoc.exe是使用c++編寫的proto文件的編譯工具鄙币,文章后面我們會介紹使用protoc.exe編譯proto文件產(chǎn)生對應(yīng)的java類蹂随。

步驟三:新建Maven工程

在這個演示的案例中,我們使用maven構(gòu)建項(xiàng)目绩衷。然后在src/main下新增protos目錄存放.proto文件激率。
項(xiàng)目的目錄結(jié)構(gòu)如下:


項(xiàng)目結(jié)構(gòu)

因?yàn)槲覀冞@里使用的是java乒躺,所以要引入protobuf-java.jar來操作protobuf。我們使用的maven宪肖,所以直接在pom.xml中加入protobuf-java.jar的依賴。完整的pom.xml如下圖:

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.protobuf</groupId>
  <artifactId>myprotobuflearn</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>myprotobuflearn</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.10</version>
          <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.4.0</version>
        </dependency>
      </dependencies>
</project>

步驟四:編譯proto文件

這一步我們需要使用下載的protoc.exe文件編譯proto文件,產(chǎn)生對應(yīng)的java類壤短。
首先慨仿,把protoc.exe拷貝到工程src/main/protos目錄下
然后,把步驟一所編寫的proto文件也拷貝到src/main/protos目錄下
進(jìn)入cmd命令行帘撰,進(jìn)入protoc.exe所在路徑万皿,輸入如下命令:

protoc --java_out=../java PersonMsg.proto

因?yàn)槲覉?zhí)行此命令時牢硅,protoc.exe和PersonMsg.proto在同一目錄下,所以不用指定proto_path參數(shù)(默認(rèn)會掃描protoc.exe所在目錄的proto文件)综苔。在這里指定生成java類所在目錄為protos同級目錄java文件夾下位岔。
完整的命令格式:

protoc.exe --proto_path=$PROTO_DIR --java_out=$JAVA_OUT_DIR  xxx.proto

說明:
1.proto_path是要編譯的proto文件所在文件夾路徑,protoc.exe會掃描這個路徑,找到后面要求編譯的proto文件
2.java_out是編譯生成的java類存放的路徑
3.最后就是要編譯的proto文件的路徑

執(zhí)行編譯命令后瞧剖,我們?nèi)サ絪rc/main/java目錄下查看是否有java類生成可免。


PersonMsg.java

步驟四:編寫測試類

上面我們已經(jīng)成功編譯protoc文件生成了對應(yīng)Java類浇借,現(xiàn)在我們就可以編寫一個測試類驗(yàn)證一下protobuf的序列化和反序列化。
回到我們maven工程巾遭,在src/main/test中新增測試類PersonTest.java,代碼如下:

package com.simple;

import static org.junit.Assert.*;

import java.io.IOException;
import org.junit.Test;
import com.simple.PersonMsg.Person;

public class PersonMsgTest {

    
    @Test
    public void testSerilize() throws IOException{
        Person.Builder personBuilder = Person.newBuilder();//(1)
        
        personBuilder.setName("changzhang");
        personBuilder.setAge(18);
        personBuilder.setEmail("123456789@qq.com");
        personBuilder.setPhoneNumber("98765432");
        
        Person orginPerson = personBuilder.build();//(2)
        
        //序列化originPerson對象吼和,轉(zhuǎn)換成byte數(shù)組
        byte[] byteArray = orginPerson.toByteArray();//(3)
        
        
        //反序列化
        Person newPerson = Person.parseFrom(byteArray);//(4)
        
        assertEquals(newPerson.getName(),orginPerson.getName());
        assertEquals(newPerson.getAge(), orginPerson.getAge());
        assertEquals(newPerson.getEmail(), orginPerson.getEmail());
        assertEquals(newPerson.getPhoneNumber(), orginPerson.getPhoneNumber());
    }
}

說明:
(1)在protobuf中使用builder模式構(gòu)造序列化對象炫乓。
(2)調(diào)用build方法構(gòu)造對象献丑,對象已經(jīng)構(gòu)造就不能改變。
(3) 使用toByteArray方法箩做,把originPerson序列化成byte數(shù)組
(4)使用parseFrom方法反序列化筐摘,傳入剛剛的byte數(shù)組
序列化和反序列化說明咖熟,請參考官網(wǎng)guide->Tutorials->java里面的Parsing and Serialization內(nèi)容(連接

運(yùn)行下junit,ok!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末郭赐,一起剝皮案震驚了整個濱河市确沸,隨后出現(xiàn)的幾起案子罗捎,更是在濱河造成了極大的恐慌,老刑警劉巖桨菜,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倒得,死亡現(xiàn)場離奇詭異,居然都是意外死亡谊路,警方通過查閱死者的電腦和手機(jī)菩彬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酷麦,“玉大人喉恋,你說我怎么就攤上這事『簦” “怎么了氓鄙?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵抖拦,是天一觀的道長。 經(jīng)常有香客問我噩茄,道長复颈,這世上最難降的妖魔是什么耗啦? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任衅谷,我火速辦了婚禮,結(jié)果婚禮上玩郊,老公的妹妹穿的比我還像新娘枉阵。我一直安慰自己兴溜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布诗宣。 她就那樣靜靜地躺著召庞,像睡著了一般篮灼。 火紅的嫁衣襯著肌膚如雪徘禁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天娘荡,我揣著相機(jī)與錄音炮沐,去河邊找鬼央拖。 笑死鹉戚,一個胖子當(dāng)著我的面吹牛抹凳,可吹牛的內(nèi)容都是我干的失都。 我是一名探鬼主播粹庞,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼流码!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起漫试,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤外构,失蹤者是張志新(化名)和其女友劉穎典勇,沒想到半個月后割笙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了伏伯。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片说搅。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖候引,靈堂內(nèi)的尸體忽然破棺而出澄干,到底是詐尸還是另有隱情傻寂,我是刑警寧澤疾掰,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布徐紧,位于F島的核電站,受9級特大地震影響拂檩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜稻励,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一愈涩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧履婉,春花似錦、人聲如沸辑奈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽胯究。三九已至唐片,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間费韭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工抢埋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人揪垄。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓饥努,卻偏偏與公主長得像,于是被迫代替她去往敵國和親酷愧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 由于工程項(xiàng)目中擬采用一種簡便高效的數(shù)據(jù)交換格式乍迄,百度了一下發(fā)現(xiàn)除了采用 xml士败、JSON 還有 ProtoBuf(...
    黃海佳閱讀 48,640評論 1 23
  • Protobuf全稱Protocol Buffers,簡稱GPB谅将、PB,是QQ等IM采用的協(xié)議邦投,比XML、XMPP...
    NinaX閱讀 6,337評論 0 2
  • 1 Introduction Protocol Buffers是在網(wǎng)絡(luò)通訊或者數(shù)據(jù)存儲時用到的一種語言無關(guān)志衣、平臺無...
    天才木木閱讀 3,166評論 22 9
  • 0.前言 上一章主要寫了一些基礎(chǔ)語法念脯,命名規(guī)范等,但是只有這些明顯是不夠的绿店,也無法實(shí)現(xiàn)我們自己想要的結(jié)果庐橙,今天來主...
    紫荊峰閱讀 355評論 0 1
  • 人生的最大悲劇是:自由也許可能得到,而我們卻經(jīng)年累月將自己限于同樣的模式中态鳖。----Bryan Johnson 最...
    紫苑閱讀 449評論 3 5