protobuf 新手,需要您的建议。
我有一个 JMS 订阅者,它正在从 TIBCO 队列接收消息(类型 -> com.tibco.tibjmsTibjmsBytesMessage)。这些消息已作为 Protobuf 字节消息发布到队列上。作为订阅者,我已将这些 bytesMessage 转换为字节数组。由于我有 protobuf 消息的 JAVA 类 protoFile.class,因此为了反序列化字节数组,我调用 protoFile.parseFrom(byte[] data) 函数。然而,在响应中我看到所有字段的值都是空的。
有人可以建议遗漏了什么吗? 我需要的只是从 Protobuf 字节消息中读取数据并将它们分配给 java 对象。 我没有 proto 文件的架构,只有 proto 文件的已编译 JAVA 类,即 protoFile.class
蒂亚!
protobuf 消息在数据流中没有类名。我认为这样做是因为来源语言可能与接收者的语言不同。接收端点将期望给定类型并具有原始生成的代码来转换它。如果您将两端都限制为 Java,则可以将类名与数据一起发送。您甚至可以使用另一个原始消息来做到这一点。然后假设所有消息都是该类型。真正的消息和类型包含在该消息中。然后你就有了类名和数据。这是 Jms 的 MessageConverter,您可以获取适合您情况的部分内容。
原型文件
syntax = "proto3";
package jms;
option java_package = "some.package.here.jms";
option java_multiple_files = true;
message AnyMessage{
string classname = 1;
bytes bytesData = 2;
}
代码
@Slf4j
public class ProtobufJmsMessageConverter implements MessageConverter {
@Override
public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
GeneratedMessageV3 protoMsg = (GeneratedMessageV3) object;
AnyMessage wrap = AnyMessage.newBuilder().setClassname(object.getClass().getName()).setBytesData(protoMsg.toByteString()).build();
BytesMessage bytesMessage = session.createBytesMessage();
bytesMessage.writeBytes(wrap.toByteArray());
return bytesMessage;
}
@Override
public Object fromMessage(Message message) throws JMSException, MessageConversionException {
BytesMessage bytesMessage = (BytesMessage) message;
int messageLength = (int) bytesMessage.getBodyLength();
byte[] rawProtoMsg = new byte[messageLength];
bytesMessage.readBytes(rawProtoMsg);
try {
AnyMessage anyMessage = AnyMessage.parseFrom(rawProtoMsg);
Class protoClass = Class.forName(anyMessage.getClassname());
Method m = protoClass.getMethod("parseFrom", byte[].class);
Object result = m.invoke(null, anyMessage.getBytesData().toByteArray());
return result;
} catch (InvalidProtocolBufferException | ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
log.error("",e);
throw new MessageConversionException("Only AnyMessage should be sent.", e);
}
}
}