答案可能有點晚,但也許這仍然有助於某人。
在當前版本的協議緩衝區3 pack
和unpack
是available in Java。
在你的榜樣包裝可以像做:
Any anyMessage = Any.pack(protoMess.build()));
和拆包,如:
ProtoMess protoMess = anyMessage.unpack(ProtoMess.class);
這裏也是處理與嵌套Any
消息Protocol Buffers的消息的完整的例子:
ProtocolBuffers文件
一個簡單的協議緩衝器,具有嵌套Any
消息文件可能看起來像:
syntax = "proto3";
import "google/protobuf/any.proto";
message ParentMessage {
string text = 1;
google.protobuf.Any childMessage = 2;
}
一個可能的嵌套消息,然後可以是:
syntax = "proto3";
message ChildMessage {
string text = 1;
}
包裝
要建立完整的消息可以使用以下功能:
public ParentMessage createMessage() {
// Create child message
ChildMessage.Builder childMessageBuilder = ChildMessage.newBuilder();
childMessageBuilder.setText("Child Text");
// Create parent message
ParentMessage.Builder parentMessageBuilder = ParentMessage.newBuilder();
parentMessageBuilder.setText("Parent Text");
parentMessageBuilder.setChildMessage(Any.pack(childMessageBuilder.build()));
// Return message
return parentMessageBuilder.build();
}
開箱
讀取從父消息可用於以下功能的子消息:
public ChildMessage readChildMessage(ParentMessage parentMessage) {
try {
return parentMessage.getChildMessage().unpack(ChildMessage.class);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
return null;
}
}
編輯:
如果打包的消息可以有不同的類型,可以讀出typeUrl
並使用反射來解開消息。假設你有孩子的消息ChildMessage1
和ChildMessage2
你可以做到以下幾點:
@SuppressWarnings("unchecked")
public Message readChildMessage(ParentMessage parentMessage) {
try {
Any childMessage = parentMessage.getChildMessage();
String clazzName = childMessage.getTypeUrl().split("/")[1];
String clazzPackage = String.format("package.%s", clazzName);
Class<Message> clazz = (Class<Message>) Class.forName(clazzPackage);
return childMessage.unpack(clazz);
} catch (ClassNotFoundException | InvalidProtocolBufferException e) {
e.printStackTrace();
return null;
}
}
作進一步處理,你能確定消息與instanceof
的類型,這是不是很有效。如果你想獲得某種類型的消息,你應該比較typeUrl
直接:
public ChildMessage1 readChildMessage(ParentMessage parentMessage) {
try {
Any childMessage = parentMessage.getChildMessage();
String clazzName = childMessage.getTypeUrl().split("/")[1];
if (clazzName.equals("ChildMessage1")) {
return childMessage.unpack("ChildMessage1.class");
}
return null
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
return null;
}
}
難道就沒有其他辦法比這'readChildMessage'?如果我有幾十條不同的消息可以進來,會怎麼樣?只需添加新的'try-catch'塊?即使是「開關盒」等也是絕對不能接受的。 – Sorona
好問題,我忘了補充一下,你可以把打包的消息的名字作爲'typeURL'。這允許通過反射來解壓縮任何消息或直接決定如何處理消息。我在回答中添加了兩個示例,我希望這有助於。 – sundance
太棒了!它幫助了我! – FisherCoder