34.2. 消息
概述
消息对象使用以下抽象模型代表信息:
- 消息正文
- 消息标头
- 消息附加
消息正文和消息标头可以是任意类型(它们声明为类型 Object
),消息附加被声明为类型为 javax.activation.DataHandler
,它可以包含任意 MIME 类型。如果您需要获得消息内容的一致性,您可以使用类型转换器机制将正文和标头转换为另一种类型,可能使用 marshalling 和 unmarshalling 机制。
Apache Camel 消息的一个重要特性是它们支持 延迟创建 消息正文和标头。在某些情况下,这意味着消息可以通过路由,而无需完全解析消息。
Message 接口
org.apache.camel.Message 接口定义了访问消息正文、消息标头和消息附加的方法,如 例 34.2 “消息接口” 所示。
例 34.2. 消息接口
// Access the message body Object getBody(); <T> T getBody(Class<T> type); void setBody(Object body); <T> void setBody(Object body, Class<T> type); // Access message headers Object getHeader(String name); <T> T getHeader(String name, Class<T> type); void setHeader(String name, Object value); Object removeHeader(String name); Map<String, Object> getHeaders(); void setHeaders(Map<String, Object> headers); // Access message attachments javax.activation.DataHandler getAttachment(String id); java.util.Map<String, javax.activation.DataHandler> getAttachments(); java.util.Set<String> getAttachmentNames(); void addAttachment(String id, javax.activation.DataHandler content) // Access the message ID String getMessageId(); void setMessageId(String messageId);
有关消息接口中方法的完整描述,请参阅 第 44.1 节 “消息接口”。
lazy 创建正文、标头和附加
Apache Camel 支持 lazy 创建正文、标头和附加。这意味着,在需要消息正文、消息标头或消息附加之前,不会创建代表消息正文、消息标头或消息附加的对象。
例如,请考虑以下路由,它从 In 消息访问 foo
消息标头 :
from("SourceURL") .filter(header("foo") .isEqualTo("bar")) .to("TargetURL");
在这个路由中,如果我们假设 SourceURL 引用的组件支持 lazy 创建,则在执行 标头("foo")
调用前,不会实际解析 In 消息标头。此时,底层消息实施会解析标头并填充标头映射。在到达路由末尾之前,消息正文 不会被解析,在 to ("TargetURL")
调用中。此时,正文将转换为将其写入目标端点 TargetURL 所需的格式。
在填充正文、标头和附加前等待最后一次可能的时间,您可以确保避免不必要的类型转换。在某些情况下,您可以完全避免解析。例如,如果路由不包含对消息标头的显式引用,则消息可以在不解析标头的情况下遍历路由。
在实践中实施是否实施 lazy 创建取决于底层组件实施。通常,lazy 创建对于创建消息正文、消息标头或消息附加的成本较高。有关实现支持延迟创建的消息类型的详情,请参考 第 44.2 节 “实施消息接口”。
lazy 创建消息 ID
Apache Camel 支持 lazy 创建消息 ID。也就是说,只有在您实际调用 getMessageId ()
方法时,才会生成消息 ID。此方法的 DefaultExchange.getExchangeId ()
实现将 ID 生成委托给通过 CamelContext
注册的 UUID 生成器。
如果端点实现了需要唯一消息 ID 的协议,一些端点实现会隐式调用 getMessageId ()
方法。特别是,JMS 消息通常包含一个包含唯一消息 ID 的标头,因此 JMS 组件会自动调用 getMessageId ()
获取消息 ID (这由 JMS 端点上的 messageIdEnabled
选项控制)。
有关如何使用 CamelContext
注册 UUID 生成器的详情,请参考 第 34.4 节 “built-In UUID Generators”。
初始消息格式
In 消息的初始格式由源端点决定,Out 消息的初始格式由目标端点决定。如果底层组件支持 lazy 创建,则消息会保留 unparsed,直到应用程序被明确访问为止。大多数 Apache Camel 组件以相对原始的形式创建消息正文,例如,使用 byte[] 等类型来代表消息正文,如 byte[]
、ByteBuffer
、InputStream
或 OutputStream
。这样可确保创建初始消息所需的开销最小。如果更详细的信息格式是所需的组件,通常依赖于 类型转换器 或嵌套 处理器。
类型转换器
消息的初始格式无关紧要,因为您可以使用内置类型转换器轻松将消息从一个格式转换为另一个格式(请参阅 第 34.3 节 “built-In Type Converters”)。Apache Camel API 中有多种方法公开类型转换功能。例如,convertBodyTo (Class type)
方法可以插入到路由中,以转换 In 消息的正文,如下所示:
from("SourceURL").convertBodyTo(String.class).to("TargetURL");
其中 In 消息的正文转换为 java.lang.String
。以下示例演示了如何在 In 消息正文的末尾附加字符串:
from("SourceURL").setBody(bodyAs(String.class).append("My Special Signature")).to("TargetURL");
在向末尾附加字符串之前,邮件正文将转换为字符串格式。在本例中,不需要显式转换消息正文。您还可以使用:
from("SourceURL").setBody(body().append("My Special Signature")).to("TargetURL");
其中 append ()
方法会在附加其参数前自动将消息正文转换为字符串。
在消息中类型转换方法
org.apache.camel.Message 接口公开一些明确执行类型转换的方法:
-
getBody (Class<T> type)
mvapich-wagonReturns 消息正文作为类型T
。 -
getHeader (String name, Class<T> type)
criu-wagonReturns 命名的标头值为 type,T
.
有关支持的转换类型的完整列表,请参阅 第 34.3 节 “built-In Type Converters”。
转换为 XML
除了支持简单类型(如 byte[]
、ByteBuffer
、String
等)之间的转换外,内置的类型转换器还支持转换为 XML 格式。例如,您可以将消息正文转换为 org.w3c.dom.Document
类型。这个转换比简单的转换更为昂贵,因为它涉及解析整个消息,然后创建节点树来代表 XML 文档结构。您可以转换为以下 XML 文档类型:
-
org.w3c.dom.Document
-
javax.xml.transform.sax.SAXSource
与更简单的转换相比,XML 类型转换具有更严格的适用性。因为并非所有消息正文都符合 XML 结构,所以您必须记住此类型转换可能会失败。另一方面,有许多场景,路由器只处理 XML 消息类型。
Marshalling 和 unmarshalling
Marshalling 涉及将高级别格式转换为低级格式,而 unmarshalling 涉及将低级格式转换为高级别格式。以下两个处理器用于在路由中执行 marshalling 或 unmarshalling:
-
marshal()
-
unmarshal()
例如,要从文件中读取序列化 Java 对象并将其 unmarshal 到 Java 对象,您可以使用 例 34.3 “unmarshalling a Java 对象” 中显示的路由定义。
例 34.3. unmarshalling a Java 对象
from("file://tmp/appfiles/serialized") .unmarshal() .serialization() .<FurtherProcessing> .to("TargetURL");
最终消息格式
当 In 消息到达路由末尾时,目标端点必须能够将消息正文转换为可写入物理端点的格式。相同的规则适用于到达源端点的 Out 消息。这个转换通常是使用 Apache Camel 类型转换器隐式执行。通常,这涉及从低级格式转换到另一个低级格式,例如从 byte[]
数组转换为 InputStream
类型。