Protobuf Java使用嚮導

LuckyJiang-2019發表於2017-01-22

【Windows】

1.準備兩個檔案proto.exe,protobuf-java-2.5.0.jar。

如果是protobuf-2.5.0.zip,將其解壓縮後,用VS2010開啟其中的vsprojects工程,編譯後,將proto.exe拷貝待用。


2.建立一個Java工程test-protocbuf

將proto.exe拷貝至test-protocbuf下;

工程下建立proto資料夾,用來存放xxx.proto檔案;

編寫規範的proto檔案兵儲存至proto資料夾下;

生成Java檔案,使用cmd命令編譯這個proto檔案:

在protc.exe目錄下執行protoc  --version可檢視protoc版本;

在protc.exe目錄下執行protoc  --java_out=./src  ./proto/xxx.proto;

在指定目錄下將生成一個Java檔案,將其引入到MyEclipse中;

再把protobuf-java-2.5.0.jar引入到工程libs目錄中;

package com.leehongee.netserver.net.bean;
 
option java_package = "com.leehongee.netserver.net.bean";
option java_outer_classname = "Request";
 
message request_Net {
 required string cmd = 1;
 optional int32 keycode = 2;      
 optional sint32 posX = 3;
 optional sint32 posY = 4;
 optional bool onOrOff = 5;
 optional bool ontouch = 6;
}

3.使用方法呼叫序列化:

Request .request_Net .Builder builder=Request .request_Net ..newBuilder();
builder.setCmd("ontouch");
Request .request_Net  request=builder.builder();
byte[] buffer=request.toByteAarray();

4.使用反序列化

try{
    Request .request_Net  request     = Request .request_Net .parseFrom(buffer);
   }
   catch(Exception ex){
       System.out.println(ex.getMessage());
   }


例:編寫msg.proto檔案

為需要序列化的資料介面加入一個message屬性,為每一個欄位指定名稱和型別。注意message 的名稱不能與java_outer_classname 名稱相同,不然編譯不過。

option java_package = "com.protobuftest.protobuf"; 
option java_outer_classname = "PersonProbuf"; 
 
message Person { 
  required string name = 1; 
  required int32 id = 2; 
  optional string email = 3; 
 
  enum PhoneType { 
    MOBILE = 0; 
    HOME = 1; 
    WORK = 2; 
  } 
 
  message PhoneNumber { 
    required string number = 1; 
    optional PhoneType type = 2 [default = HOME]; 
  } 
 
  repeated PhoneNumber phone = 4; 
 
  message CountryInfo {
          required string name = 1;
          required string code = 2;
          optional int32 number = 3;
  }
} 
 
message AddressBook { 
  repeated Person person = 1; 
} 

4.進行測試

import java.util.List;
 
import com.google.protobuf.InvalidProtocolBufferException;
import com.protobuftest.protobuf.PersonProbuf;
import com.protobuftest.protobuf.PersonProbuf.Person;
import com.protobuftest.protobuf.PersonProbuf.Person.PhoneNumber;
 
public class TestPb {
 
/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
PersonProbuf.Person.Builder builder = PersonProbuf.Person.newBuilder();
builder.setEmail("kkk@email.com");
builder.setId(1);
builder.setName("TestName");
builder.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().setNumber("131111111").setType(PersonProbuf.Person.PhoneType.MOBILE));
builder.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().setNumber("011111").setType(PersonProbuf.Person.PhoneType.HOME));
 
Person person = builder.build();
byte[] buf = person.toByteArray();
 
try {
Person person2 = PersonProbuf.Person.parseFrom(buf);
System.out.println(person2.getName() + ", " + person2.getEmail());
List<PhoneNumber> lstPhones = person2.getPhoneList();
for (PhoneNumber phoneNumber : lstPhones) {
System.out.println(phoneNumber.getNumber());
}
} catch (InvalidProtocolBufferException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(buf);
}
}


***********************************************

*******************************
生成java檔案:PersonProbuf.java 
*******************************

工程檔案結構:


【理論知識點】

全稱是Protocol Buffers,是Google內部用的一種高效的、可擴充套件的對結構化資料進行編碼的格式規範,Google內部很多程式間的通訊協議都用了protobuf。是用於結構化資料序列化的靈活、高效、自動的方法,有如XML,不過它更小、更快、也更簡單。你可以定義自己的資料結構,然後使用程式碼生成器生成的程式碼來讀寫這個資料結構。你甚至可以在無需重新部署程式的情況下更新資料結構。


用於序列和反序列所有基於Google Protobuf格式的各種訊息。 能夠將protobuf格式還原成XML、JSON和HTML等文字格式。

將物件轉成二進位制資料進行傳輸,缺點是可讀性差,但是佔用空間小,有時候採用protobuf來摒棄傳統的XML傳輸資料。

google官方連線地址  http://code.google.com/p/protobuf/downloads/list

選擇proto.exe壓縮包protoc-2.5.0.zip和protobuf-java-2.5.0.jar壓縮包protobuf-2.5.0.zip

下載一個protobuf-java-2.5.0.jar檔案(注意,要與你剛才下的proto.exe版本相同,否則可能出現編譯通不過現象)


備註:限定修飾符 required ,optional ,repeated

required: 表示是一個必須欄位,必須相對於傳送方,在傳送訊息之前必須設定該欄位的值,對於接收方,必須能夠識別該欄位的意思。

optional:表示是一個可選欄位,可選對於傳送方,在傳送訊息時,可以有選擇性的設定或者不設定該欄位的值。

repeated:表示該欄位可以包含0~N個元素。其特性和optional一樣,但是每一次可以包含多個值。


【摘錄】

一條訊息資料,用protobuf序列化後的大小是json的10分之一,xml格式的20分之一,是二進位制序列化的10分之一,總體看來ProtoBuf的優勢還是很明顯的

protobuf是google提供的一個開源序列化框架,類似於XML,JSON這樣的資料表示語言,詳情訪問protobuf的google官方網站

protobuf在google中是一個比較核心的基礎庫,作為分散式運算涉及到大量的不同業務訊息的傳遞,如何高效簡潔的表示、操作這些業務訊息在google這樣的大規模應用中是至關重要的。而protobuf這樣的庫正好是在效率、資料大小、易用性之間取得了很好的平衡。

protobuf簡單總結如下幾點:

  1. 靈活(方便介面更新)、高效(效率經過google的優化,傳輸效率比普通的XML等高很多);
  2. 易於使用;開發人員通過按照一定的語法定義結構化的訊息格式,然後送給命令列工具,工具將自動生成相關的類,可以支援java、c++、python等語言環境。通過將這些類包含在專案中,可以很輕鬆的呼叫相關方法來完成業務訊息的序列化與反序列化工作。
  3. 多語言支援;原生支援c++,java,python

個人總結的適用protobuf的場合

  1. 需要和其它系統做訊息交換的,對訊息大小很敏感的。那麼protobuf適合了,它語言無關,訊息空間相對xml和json等節省很多。
  2. 小資料的場合。如果你是大資料,用它並不適合。
  3. 專案語言是c++,java,python的,因為它們可以使用google的源生類庫,序列化和反序列化的效率非常高。其它的語言需要第三方或者自己寫,序列化和反序列化的效率不保證。
  4. 總體而言,protobuf還是非常好用的,被很多開源系統用於資料通訊的工具,在google也是核心的基礎庫。

此外,還有更牛叉的facebook的thrift,2007年由Facebook開發,之後在2008年加到Apache計劃中。是一個跨語言的輕量級RPC訊息和資料交換框架,Thrift能生成的語言有: C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml,這是它的一大優點。


相關文章