第 2 章 路由构建的基本原则
摘要
Apache Camel 提供了几个处理器和组件,您可以在路由中连接在一起。本章介绍了使用提供的构建块构建路由的原则。
2.1. Pipeline 处理
概述
在 Apache Camel 中,pipelining 是在路由定义中连接节点的主要范例。管道概念或许对 UNIX 操作系统的用户最熟悉,其中用于加入操作系统命令。例如,ls | more
是将目录列表 ls
传送到 page-scrolling 实用程序的命令示例,更多
。管道的基本理念是,其中一个 命令的输出 被引入到下一个命令 的输入 中。路由时的自然模拟是,从一个处理器中要复制到下一处理器的 In 消息中的 Out 消息。
处理器节点
路由中的每个节点(初始端点除外)都是 处理器,它们从 org.apache.camel.Processor
接口继承。换句话说,处理器制作 DSL 路由的基本构建块。例如,filter ()
, delayer ()
, setBody ()
, setHeader ()
, 和 to ()
等 DSL 命令代表处理器。当考虑处理器如何连接在一起以构建路由时,务必要区分两种不同的处理方法。
第一种方法是处理器只修改交换的 In 消息,如 图 2.1 “处理器修改消息” 所示。在这种情况下,交换的 Out 消息保持 null
。
图 2.1. 处理器修改消息
以下路由显示了一个 setHeader ()
命令,它通过添加(或修改) BillingSystem
标题来修改当前的 In 消息:
from("activemq:orderQueue") .setHeader("BillingSystem", xpath("/order/billingSystem")) .to("activemq:billingQueue");
第二种方法是,处理器会创建一个 Out 消息来代表处理的结果,如 图 2.2 “处理器创建注销消息” 所示。
图 2.2. 处理器创建注销消息
以下路由显示了一个 transform ()
命令,该命令使用包含字符串 DummyBody
的消息正文创建 Out 消息:
from("activemq:orderQueue") .transform(constant("DummyBody")) .to("activemq:billingQueue");
其中 constant ("DummyBody")
代表一个恒定表达式。您不能直接传递字符串 DummyBody
,因为要 transform ()
的参数必须是 expression 类型。
InOnly Exchanges 的管道
图 2.3 “InOnly Exchanges 的管道示例” 显示了用于 InOnly 交换的处理器管道示例。处理器 A 通过修改 In 消息来的行为,而处理器 B 和 C 则创建 Out 消息。路由构建器将处理器连接在一起,如下所示。特别是,处理器 B 和 C 以 管道 的形式链接在一起:也就是说,处理器 B 的 Out 消息会在将交换发送到处理器 C 之前移到 In 消息,处理器 C's Out 消息会移到 In 消息,然后再将交换进入生成者端点。因此,处理器的输出和输入加入到持续管道中,如 图 2.3 “InOnly Exchanges 的管道示例” 所示。
图 2.3. InOnly Exchanges 的管道示例
Apache Camel 默认使用管道模式,因此您不需要使用任何特殊语法在路由中创建管道。例如,以下路由从 userdataQueue
队列拉取消息,通过 Velocity 模板传输消息(以文本格式生成客户地址),然后将生成的文本地址发送到队列 envelopeAddresses
:
from("activemq:userdataQueue") .to(ExchangePattern.InOut, "velocity:file:AdressTemplate.vm") .to("activemq:envelopeAddresses");
其中 Velocity 端点 velocity:file:AddressTemplate.vm
指定 Velocity 模板文件 file:AddressTemplate.vm
的位置。to ()
命令将交换模式更改为 InOut,然后将交换模式更改为 Velocity 端点,然后将它改回到 InOnly。有关 Velocity 端点的更多详细信息,请参阅 Apache Camel 组件参考指南 中的 Velocity。
InOut Exchanges 的管道
图 2.4 “InOut Exchange 的管道示例” 显示 InOut Exchanges 的处理器管道示例,您通常使用它来支持远程过程调用(RPC)语义。处理器 A、B 和 C 以管道的形式连接在一起,以及下一个处理器的输入信息。producer 端点生成的最终 Out 消息将以所有方式发回给消费者端点,其中提供了对原始请求的回复。
图 2.4. InOut Exchange 的管道示例
请注意,为了支持 InOut Exchange 模式,路由(无论是生成者端点还是某种其他类型的处理器)中的最后一个节点都会创建 Out 消息。否则,任何连接到消费者端点的客户端都会挂起并等待回复消息。您应该注意,并非所有制作者端点都会创建 Out 消息。
通过处理传入的 HTTP 请求,请考虑以下路由来处理支付请求:
from("jetty:http://localhost:8080/foo") .to("cxf:bean:addAccountDetails") .to("cxf:bean:getCreditRating") .to("cxf:bean:processTransaction");
如果传入的支付请求是通过 Web 服务的管道处理,cxf:bean:addAccountDetails
, cxf:cxf:bean:getCreditRating
, 和 cxf:bean:processTransaction
。最后的 Web 服务处理 事务
生成通过 JETTY 端点发回的响应(出 消息)。
当管道仅由一系列端点组成时,也可以使用以下替代语法:
from("jetty:http://localhost:8080/foo") .pipeline("cxf:bean:addAccountDetails", "cxf:bean:getCreditRating", "cxf:bean:processTransaction");
InOptionalOut Exchanges 的管道
InOptionalOut Exchanges 的管道与 图 2.4 “InOut Exchange 的管道示例” 中的管道基本相同。InOut 和 InOptionalOut 之间的区别在于,使用 InOptionalOut 交换模式的交换允许将 null Out 消息作为回复。也就是说,如果 In OptionalOut 交换,则会将 null
Out 消息复制到管道中下一节点的 In 消息。相反,如果 InOut Exchange,将丢弃 null
Out 消息,并且来自当前节点的原始 In 消息会被复制到下一节点的 In 消息。