數據交換的方式不少好比:XML,JSON,Protobuf。雖然protobuf很流行,而且系出名門,但是沒怎麼用過。經過閱讀google developers裏關於protocal-buffers的內容基本能夠使用它了。若是你訪問該連接https://developers.google.com/protocol-buffers/ 失敗的話,肯能須要×××服務。java
語言手冊:https://developers.google.com/protocol-buffers/docs/proto
eclipse
Protobuf-Java:https://developers.google.com/protocol-buffers/docs/javatutorial
ide
下載地址:https://developers.google.com/protocol-buffers/docs/downloads
學習
若是是Windows系統建議下載protoc-2.6.0-win32.zip,這樣便可省去編譯。ui
官方提供的C++,Python,Java的運行庫下載:https://code.google.com/p/protobuf/downloads/list 這裏須要注意的是運行庫的版本須要和protoc的版本對應。
this
下文是經過使用protocal-buffers官網提供的一個數據格式的例子來熟悉protocal buffer在Java開發中的基本使用方法。google
1.編寫一個.proto文件命名爲:addressbook.proto,該文件內容來自protocal-buffers官網spa
package tutorial; option java_package = "com.example.tutorial"; option java_outer_classname = "AddressBookProtos"; 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 AddressBook { repeated Person person = 1; }
2.使用protoc-2.6.0-win32.zip解壓後的protoc.exe生成Java類3d
查詢protoc.exe幫助:code
D:\__dev\jar\protobuff>protoc.exe -h
生成Java類:
D:\__dev\jar\protobuff>protoc.exe --proto_path=F:\__eclipse\test\proto --java_out=F:\__eclipse\test\src F:\__eclipse\test\proto\addressbook.proto
在Eclipse中的項目目錄結構圖以下:
說明:
上圖中:addressbook.proto數據格式文件,AddressBookProtos.java是生成的java類,protobuf-java-2.5.0.jar是Java運行時類庫。
3.使用AddressBookProtos類來實現對象的序列號和反序列化,瞭解Protocol-buffers jar的相關API
代碼實例:
package com.example.test; import java.util.Arrays; import com.example.tutorial.AddressBookProtos.AddressBook; import com.example.tutorial.AddressBookProtos.Person; import com.google.protobuf.InvalidProtocolBufferException; public class AddressBookProtoUse { public static void main(String[] args) { //構建一個Person對象 Person person = Person .newBuilder() .setEmail("zhangsan@163.com") .setId(10086) .setName("zhangsan") .addPhone( Person.PhoneNumber.newBuilder().setNumber("186") .setType(Person.PhoneType.HOME).build()) .build(); System.out.println("打印輸出Person對象信息:"); System.out.println(person); System.out.println("Person對象調用toString()方法:"); System.out.println(person.toString()); System.out.println("Person對象字段是否初始化:" + person.isInitialized()); // 序列號 System.out.println("Person對象調用toByteString()方法:"); System.out.println(person.toByteString()); System.out.println("Person對象調用toByteArray()方法:"); System.out.println(Arrays.toString(person.toByteArray())); try { System.out.println("反序列化後的對象信息:"); // 反序列化 Person newPerson = Person.parseFrom(person.toByteArray()); System.out.println(newPerson); newPerson = Person.parseFrom(person.toByteString()); System.out.println(newPerson); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } // 向地址簿添加兩條Person信息 AddressBook.Builder books = AddressBook.newBuilder(); books.addPerson(person); books.addPerson(Person.newBuilder(person).setEmail("tom@163.com") .build()); System.out.println("AddressBook對象信息:"); System.out.println(books.build()); } }
運行結果:
打印輸出Person對象信息: name: "zhangsan" id: 10086 email: "zhangsan@163.com" phone { number: "186" type: HOME } Person對象調用toString()方法: name: "zhangsan" id: 10086 email: "zhangsan@163.com" phone { number: "186" type: HOME } Person對象字段是否初始化:true Person對象調用toByteString()方法: <ByteString@89ec59 size=40> Person對象調用toByteArray()方法: [10, 8, 122, 104, 97, 110, 103, 115, 97, 110, 16, -26, 78, 26, 16, 122, 104, 97, 110, 103, 115, 97, 110, 64, 49, 54, 51, 46, 99, 111, 109, 34, 7, 10, 3, 49, 56, 54, 16, 1] 反序列化後的對象信息: name: "zhangsan" id: 10086 email: "zhangsan@163.com" phone { number: "186" type: HOME } name: "zhangsan" id: 10086 email: "zhangsan@163.com" phone { number: "186" type: HOME } AddressBook對象信息: person { name: "zhangsan" id: 10086 email: "zhangsan@163.com" phone { number: "186" type: HOME } } person { name: "zhangsan" id: 10086 email: "tom@163.com" phone { number: "186" type: HOME } }
探究AddressBookProtos類:
a.構造Person對象,Person類繼承自com.google.protobuf.GeneratedMessage類,而GeneratedMessage類繼承自AbstractMessage類,而且實現了序列化接口Serializable。在AbstractMessage類中重寫了toString()方法,具體內容以下:
@Override public final String toString() { return TextFormat.printToString(this); }
因而有了Person對象調用toString()方法後直接輸出Person對象的文本內容。
b.toByteString()返回的ByteString是一個不可變的byte序列,由AbstractMessage類實現。toByteArray()返回byte[]。這兩個方法都是對象進行序列化的方法。
c.isInitialized()判斷對象的字段是否初始化,該方法與Person類的initFields()方法相關。
initFields()源代碼:
private void initFields() { name_ = ""; id_ = 0; email_ = ""; phone_ = java.util.Collections.emptyList(); }
initFields()方法的調用是在Person類的默認實力對象初始化以後調用的,在Person類的靜態代碼塊中能夠看到:
static { defaultInstance = new Person(true); defaultInstance.initFields(); }
d.Person類提供了一系列的反序列化的重載方法用來說數據反序列化爲Person對象。
e.關於Person對象的Build
Person類中有一個Builder的內部類,該類用來構建Person對象,而且爲Person對象添加數據。
public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder<Builder> implements com.example.tutorial.AddressBookProtos.PersonOrBuilder
4.經過學習官網的實例,手繪一張Java使用protobuf的基本流程圖