Protobuf 協議的Java應用sample
Protobuf協議,全稱:Protocol Buffer
它跟JSON,XML一樣,是一個規定好的資料傳播格式。不過,它的序列化和反序列化的效率太變態了……
來看看幾張圖你就知道它有多變態。
Protobuf的Java例項
一、 安裝Protobuf
如果你是Windows環境,則還要下載多一個東西。protobuf-2.5.0-windows.zip。
解壓protobuf-2.5.0-windows.zip,把protoc.exe放在Protobuf安裝目錄下的src裡。(其實放哪都可以)
二、 配置環境變數
編輯系統變數Path,新增Protoc.exe的存放目錄。
三、 Eclipse新建專案
我使用maven構建protobuf專案,方便引入protobuf-Java-2.5.0.jar依賴。
在專案根目錄建立proto資料夾,存放proto檔案。
maven依賴pom.xml
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.5.0</version >
</dependency>
四、編寫.proto檔案
在proto資料夾下編寫person-entity.proto,如下(proto協議的規則點這檢視)
option java_outer_classname = "PersonEntity";//生成的資料訪問類的類名
message Person {
required int32 id = 1;//同上
required string name = 2;//必須欄位,在後面的使用中必須為該段設定值
optional string email = 3;//可選欄位,在後面的使用中可以自由決定是否為該欄位設定值
}
四、使用protoc.exe編譯成java類
有兩種方法:
1. 使用JavaRumtime執行cmd命令
2. 直接開啟cmd執行命令也行。
1. 使用Java Rumtime執行cmd命令
util包下新建GenerareClass類
/**
* protoc.exe
* @author ganhaibin
*
*/
public class GenerateClass {
public static void main(String[] args) {
String protoFile = "person-entity.proto";//
String strCmd = "d:/dev/protobuf-master/src/protoc.exe -I=./proto --java_out=./src/main/java ./proto/"+ protoFile;
try {
Runtime.getRuntime().exec(strCmd);
} catch (IOException e) {
e.printStackTrace();
}//通過執行cmd命令呼叫protoc.exe程式
}
}
命令格式如下。
protoc.exe -I=proto的輸入目錄 --java_out=java類輸出目錄 proto的輸入目錄包括包括proto檔案
2. 直接開啟cmd執行命令
生成的PersonEntity.java類
五、測試
編寫Test類,模擬序列化和反序列化過程。
public class Test {
public static void main(String[] args) throws IOException {
//模擬將物件轉成byte[],方便傳輸
PersonEntity.Person.Builder builder = PersonEntity.Person.newBuilder();
builder.setId(1);
builder.setName("ant");
builder.setEmail("[email protected]");
PersonEntity.Person person = builder.build();
System.out.println("before :"+ person.toString());
System.out.println("===========Person Byte==========");
for(byte b : person.toByteArray()){
System.out.print(b);
}
System.out.println();
System.out.println(person.toByteString());
System.out.println("================================");
//模擬接收Byte[],反序列化成Person類
byte[] byteArray =person.toByteArray();
Person p2 = Person.parseFrom(byteArray);
System.out.println("after :" +p2.toString());
}
}
輸出如下
定義複雜的proto檔案
// 生成類的包名
option java_package="com.sample.protobuf";
//生成的資料訪問類的類名
option java_outer_classname="ComplexObjectTest";
message ComplexObject{
optional int32 id = 1;
optional string name = 2;
optional string email = 3;
repeated string sons = 4;
optional Gender gender = 5;
repeated Result result = 6; // 新的物件List
}
enum Gender {
MAN = 0;
WOMAN = 1;
}
message Result {
optional string url = 1;
optional string title = 2;
repeated string snippets = 3;
}
public class Brootstrap {
public static void main(String[] args) throws InvalidProtocolBufferException {
ComplexObject.Builder builder = ComplexObject.newBuilder();
builder.setId(100);
builder.setName("name");
builder.setEmail("email");
builder.addSons("Son1");
builder.addSons("Son2");
builder.setGender(Gender.MAN);
Result.Builder r = Result.newBuilder();
r.setTitle("title");
builder.addResult(r.build());
ComplexObject cob = builder.build();
System.out.println("before :" + cob.toString());
System.out.println("===========ComplexObject Byte==========");
for (byte b : cob.toByteArray()) {
System.out.print(b);
}
System.out.println();
System.out.println(cob.toByteString());
System.out.println("================================");
byte[] byteArray = cob.toByteArray();
ComplexObject cob2 = ComplexObject.parseFrom(byteArray);
System.out.println("after :" + cob2.toString());
}
}