一,、Protobuf簡介
protobuf(Google Protocol Buffers)是Google提供一個具有高效的協(xié)議數(shù)據(jù)交換格式工具庫(類似Json),但相比于Json,,Protobuf有更高的轉(zhuǎn)化效率,,時間效率和空間效率都是JSON的3-5倍。參考GitHub
二,、安裝Protobuf環(huán)境
- windows環(huán)境下載
protoc-2.5.0-win32.zip ,,下載后解壓將protoc.exe 拷貝至C:\Windows\System32 目錄下即可使用。 - linux環(huán)境下在
protobuf-2.5.0.tar.gz ,,解壓后參考README.txt 安裝環(huán)境,。
三、protobuf語法介紹
- message:代表了實體結(jié)構(gòu),,由多個消息字段(field)組成,。
- 消息字段(field): 包括數(shù)據(jù)類型、字段名、字段規(guī)則,、字段唯一標(biāo)識,、默認值。
- 數(shù)據(jù)類型:常見的原子類型都支持(在FieldDescriptor::kTypeToName中有定義)
- 字段規(guī)則:(在FieldDescriptor::kLabelToName中定義)
required:必須初始化字段,,如果沒有賦值,,在數(shù)據(jù)序列化時會拋出異常
optional:可選字段,可以不必初始化,。
repeated:數(shù)據(jù)可以重復(fù)(相當(dāng)于java 中的Array或List)
字段唯一標(biāo)識:序列化和反序列化將會使用到,。
四,、編寫.proto文件
//指定protobuf語法版本
syntax = "proto2";
//包名
option java_package = "com.lhc.protobuf";
//源文件類名
option java_outer_classname = "AddressBookProtos";
// class Person
message Person {
//required 必須設(shè)置(不能為null)
required string name = 1;
//int32 對應(yīng)java中的int
required int32 id = 2;
//optional 可以為空
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 重復(fù)的 (集合)
repeated PhoneNumber phones = 4;
}
message AddressBook {
repeated Person people = 1;
}
五,、生成java文件
windows下打開cmd窗口,執(zhí)行命令protoc -I=proto文件所在目錄 --java_out=java文件生成的根目錄(通常src/main/java) proto文件的絕對路徑 eg:protoc -I=src/main/resources/proto --java_out=src/main/java src/main/resources/proto/ProtoBufHeader.proto 生成后的文件在src/main/java目錄下,,可在.proto文件中定義包名,。
六、使用生成的java文件
@Test
public void test() {
//包頭
ProtoBufMsg.HsHeaderMsg.Builder headerBuilder = ProtoBufMsg.HsHeaderMsg.newBuilder();
headerBuilder.setSrcAddr("192.168.0.1");
headerBuilder.setDestAddr("127.0.0.1");
headerBuilder.setAckFlag(true);
headerBuilder.setSeqNo(3);
headerBuilder.setTerminalType(1);
headerBuilder.setPlatFormType(1);
HsHeaderMsg hsHeaderMsg = headerBuilder.build();
//消息實體
ProtoBufMsg.BusArrLeftMsg.Builder builder = ProtoBufMsg.BusArrLeftMsg.newBuilder();
builder.setHeader(hsHeaderMsg);
builder.setAngle(30);
builder.setAvgSpeed(55.5);
builder.setLongitude(138.11111);
builder.setLatitude(29.33333);
builder.setMsgTime("2020-12-31 11:11:00");
builder.setRouteID("6");
builder.setProductID("1");
builder.setDualSerialid("1");
builder.setIsArrLeft("1");
//data
BusArrLeftMsg data = builder.build();
//輸出對象數(shù)據(jù)
System.out.println(data.toString());
System.out.println("===== gps Byte 開始=====");
for(byte b : data.toByteArray()){
System.out.print(b);
}
System.out.println("\n" "bytes長度" data.toByteString().size());
System.out.println("===== gps Byte 結(jié)束 =====");
System.out.println("===== 使用gps 反序列化生成對象開始 =====");
BusArrLeftMsg gd = null;
try {
gd = ProtoBufMsg.BusArrLeftMsg.parseFrom(data.toByteArray());
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
System.out.print(gd.toString());
System.out.println("===== 使用gps 反序列化生成對象結(jié)束 =====");
}
七,、單元測試輸出結(jié)果
Header {
SrcAddr: "192.168.0.1"
DestAddr: "127.0.0.1"
AckFlag: true
SeqNo: 3
TerminalType: 1
PlatFormType: 1
}
Longitude: 138.11111
Latitude: 29.33333
Angle: 30.0
AvgSpeed: 55.5
MsgTime: "2020-12-31 11:11:00"
RouteID: "6"
ProductID: "1"
DualSerialid: "1"
IsArrLeft: "1"
===== gps Byte 開始=====
10321011495750464954564648464918949505546484648464924132340148117708-11354-11467976425-109-5810429858561644900000062645700000-647564661950485048454950455149324949584949584848-1261154-1181149-1101149-1021149
bytes長度107
===== gps Byte 結(jié)束 =====
===== 使用gps 反序列化生成對象開始 =====
Header {
SrcAddr: "192.168.0.1"
DestAddr: "127.0.0.1"
AckFlag: true
SeqNo: 3
TerminalType: 1
PlatFormType: 1
}
Longitude: 138.11111
Latitude: 29.33333
Angle: 30.0
AvgSpeed: 55.5
MsgTime: "2020-12-31 11:11:00"
RouteID: "6"
ProductID: "1"
DualSerialid: "1"
IsArrLeft: "1"
===== 使用gps 反序列化生成對象結(jié)束 =====
八,、總結(jié)
使用protobuf可以方便序列化和反序列化對象數(shù)據(jù),可以有效防止序列化的過程中因為協(xié)議的不一致導(dǎo)致數(shù)據(jù)解析錯誤問題,。結(jié)合消息中間件,,可以方便系統(tǒng)間的數(shù)據(jù)傳輸。
來源:https://www./content-4-810101.html
|