Apache Camel 开发指南
使用 Apache Camel 开发应用程序
摘要
使开源包含更多
红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。详情请查看我们的 CTO Chris Wright 信息 。
部分 I. 实施企业级集成模式
这部分论述了如何使用 Apache Camel 构建路由。它涵盖了基本构建块和 EIP 组件。
第 1 章 为路由定义构建块
摘要
Apache Camel 支持两个替代 域特定语言 (DSL)来定义路由:Java DSL 和 Spring XML DSL。定义路由的基本构建块是 端点 和 处理器 ,其中处理器的行为通常由表达式或逻辑 predicates 修改。 Apache Camel 可让您使用各种不同语言定义表达式和 predicates。
1.1. 实施 RouteBuilder 类
概述
要使用
域特定语言
(DSL),您可以扩展
RouteBuilder
类并覆盖其
configure()
方法(您定义路由规则)。
您可以根据需要定义多个
RouteBuilder
类。每个类都会实例化一次,并在
CamelContext
对象中注册。通常,每个
RouteBuilder
对象的生命周期由您在其中部署路由器的容器自动管理。
RouteBuilder 类
作为路由器开发人员,您的核心任务是实施一个或多个
RouteBuilder
类。您可以从继承两种替代
RouteBuilder
类:
org.apache.camel.builder.RouteBuilder
时间为适用于
部署到任何
容器类型的通用
RouteBuilder
基础类。它在
camel-core
工件中提供。
org.apache.camel.spring.SpringRouteBuilder
abrt-abrt这个基础类特别适用于 Spring 容器。特别是,它提供对以下 Spring 特定功能的额外支持:在 Spring registry 中查找
BeanRef()
Java DSL 命令,以及事务(请参阅
交易指南
)。它在
camel-spring
工件中提供。
RouteBuilder
类定义用于启动路由规则的方法(例如,
来自()、拦截器
()
和
exception()
)。
实施 RouteBuilder
例 1.1 “RouteBuilder 类的实现”
显示最小的
RouteBuilder
实施。
configure()
方法正文包含路由规则;每个规则都是单个 Java 语句。
例 1.1. RouteBuilder 类的实现
import org.apache.camel.builder.RouteBuilder; public class MyRouteBuilder extends RouteBuilder { public void configure() { // Define routing rules here: from("file:src/data?noop=true").to("file:target/messages"); // More rules can be included, in you like. // ...来自URL1.to(URL2)
的规则形式指示路由器从目录src/data
读取文件,并将它们发送到目录目标/消息
。选项?noop=true
指示路由器保留(而不是删除)src/data
目录中的源文件。 当您将contextScan
与 Spring 或 Blueprint 搭配使用以过滤RouteBuilder
类时,默认情况下,Apache Camel 将查找 singleton Bean。但是,您可以打开旧行为,使其包含使用新选项includeNonSingletons
的模型范围。
1.2. 基本 Java DSL 语法
什么是 DSL?
域特定语言(DSL)是专为特殊用途而设计的微型语言。DSL 不需要逻辑上完成,但需要足够的表达力来描述所选域中的问题。通常,DSL 不需要 专用的解析程序、解释器或编译器。DSL 可以在现有面向对象的主机语言之上 piggyback,提供 DSL 构造在主机语言 API 中彻底构造。 在假设 DSL 中请考虑以下命令序列:
command01; command02; command03;
您可以将这些命令映射到 Java 方法调用,如下所示:
command01().command02().command03()
您甚至可将块映射到 Java 方法调用。例如:
command01().startBlock().command02().command03().endBlock()
DSL 语法由主机语言 API 的数据类型隐式定义。例如,Java 方法的返回类型决定了您可以法律地调用哪些方法(与 DSL 中的下一个命令相同)。
路由器规则语法
Apache Camel 定义了一个
路由器 DSL
,用于定义路由规则。您可以使用此 DSL 在
RouteBuilder.configure()
实施的正文中定义规则。
图 1.1 “本地路由规则”
展示了定义本地路由规则的基本语法概述。
图 1.1. 本地路由规则
本地规则始终以
("
EndpointURL
")
方法开头,该方法指定路由规则的消息(
使用者端点
)来源。然后您可以在规则中添加任意较长的处理器链(如
filter()
)。您通常通过
to("
EndpointURL
")
方法关闭规则,它指定通过规则传递的消息的目标(
制作端点
)。但是,始终不需要以
to()
结束规则。在规则中指定消息目标的方法有其他方法。
您还可以通过使用特殊处理器类型(如 intercept()、
exception()
或
errorHandler
)启动规则来定义全局路由规则。全局规则不在本指南的讨论范围内。
()
消费者和制作者
本地规则始终通过定义消费者端点(使用
("
EndpointURL
")
)开始,并且通常(但并不总是)通过定义制作者端点(使用
to("
EndpointURL
")
)来结束。端点 URL
EndpointURL
可以使用部署时配置的任何组件。例如,您可以使用文件端点、
file:MyMessageDirectory
、Apache CXF 端点、
cxf:MyServiceName
或 Apache ActiveMQ 端点
activemq:queue:MyQName
。有关组件类型的完整列表,请参阅
Apache Camel 组件参考
。
Exchange
对象由元数据增强的消息组成。交换是 Apache Camel 中的集中重要性,因为交换是通过路由规则传播消息的标准表单。交换的主要特征是,如下所示:
在
message 这个过程中,使用交换封装的当前消息。在通过路由进行交换过程中,可能会修改此消息。因此,在路由开始时的
In
消息通常和路由末尾的
In
消息
不同
。
org.apache.camel.Message
类型提供了消息的通用模型,包括以下部分:
务必要意识到这是消息
的通用
模型。Apache Camel 支持各种协议和端点类型。因此,
无法
标准化邮件正文或邮件标题的格式。例如,JMS 消息正文与 HTTP 消息正文或 Web 服务消息的正文具有完全不同的格式。因此,正文和标头被声明为
对象类型
。然后,正文和标头的原始内容由创建交换实例的端点决定(即,端点会出现在
from()
命令中)。
out
messageourier- burdenis a temporary holding area for a reply message or a transformed message.某些处理节点(特别是
to()
命令)可以将
In
消息视为请求,将其发送到制作者端点,然后从该端点接收回复来修改当前消息。然后将回复消息插入到交换中的
Out
message 插槽。
通常,如果当前节点设置了
Out
消息,Apache Camel 会在将交换传递到路由中的下一个节点之前修改交换:旧的
In
消息被丢弃,并将
Out
消息移到
In
message slot。因此,回复会成为新的当前消息。如需了解 Apache Camel 如何在路由中连接节点的详情,请参考
第 2.1 节 “Pipeline 处理”
。
然而,有一个特殊情形:
Out
消息的处理方式有所不同。如果路由开头的消费者端点预期回复消息,则路由末尾的
Out
消息将被视为消费者端点的回复消息(在这种情况下,最终节点
必须创建
Out
消息,或者消费者端点会挂起)。
消息交换模式(MEP)admission-IFL-ffects 在路由中交换和端点之间的交互,如下所示:
消费者端点
the consumer 端点创建原始交换,设置 MEP 的初始值。初始值表示消费者端点是否期望收到回复(例如,
InOut
MEP)是否不是(例如
InOnly
MEP)。
生产者端点
时间为 MEP 影响生产者端点,该端点会影响路由所遇到的生产者端点(例如,交换通过
to()
节点时)。例如,如果当前 MEP 是
InOnly
,则
to()
节点不应该从端点接收回复。有时您需要更改当前的 MEP,以便自定义与制作者端点的交互。如需了解更多详细信息,请参阅
第 1.4 节 “Endpoints”
。
交换当前消息元数据的命名属性列表。
消息交换模式
使用
Exchange
对象可轻松地将消息处理规范化为
不同的消息交换模式
。例如,异步协议可以定义一个 MEP,它由一个消息组成,消息从消费者端点流到制作者端点(
仅适用
MEP)。另一方面,RPC 协议可能会定义由请求消息和回复消息(一个
InOut
MEP)组成的 MEP。目前,Apache Camel 支持以下 MEPs:
InOnly
RobustInOnly
InOut
InoptionalOut
OutOnly
RobustOutOnly
OutIn
OutOptionalIn
其中,这些消息交换模式由枚举类型中的常数来表示,即
org.apache.camel.ExchangePattern
。
有时,有一个封装多个交换实例的单一交换很有用。为了实现此目的,您可以使用一个
分组的交换
。分组交换基本上是一个交换实例,其中包含存储在
交换属性中的
Exchange
.GROUPED_EXCHANGE
java.util.List
的 Exchange 对象。有关如何使用分组交换的示例,请参阅
第 8.5 节 “聚合器”
。
处理器
是路由中的节点,可访问和修改通过路由进行的交换流。处理器可以使用
表达式或
predicate
参数,用于修改其行为。例如,
图 1.1 “本地路由规则”
中显示的规则包含一个
filter()
处理器,该处理器使用
xpath()
predicate 作为其参数。
表达式和 predicates
表达式(评估为字符串或其他数据类型)和 predicates(显示为 true 或 false)经常作为内置处理器类型的参数。例如,以下过滤器规则会传播
In
消息,只有在
foo
标头等于值
bar
时:
from("seda:a").filter(header("foo").isEqualTo("bar")).to("seda:b");
如果过滤器由 predicate、
header("foo").isEqualTo("bar")
授权。要根据消息内容构建更加复杂的 predicates 和表达式,您可以使用以下一种表达式和谓词语言(请参阅
第 II 部分 “路由表达式和指定语言”
)。
1.3. Spring XML 文件中的路由器架构
命名空间
路由器 schema>_<- the definition XML DSL-abrtbelongs 到以下 XML 模式命名空间:
http://camel.apache.org/schema/spring
指定 schema 位置
路由器模式的位置通常指定为
http://camel.apache.org/schema/spring/camel-spring.xsd
,它引用 Apache Web 站点上 schema 的最新版本。例如,Apache Camel Spring 文件的 root
Bean
元素通常配置为
例 1.2 “指定路由器架构位置”
。
例 1.2. 指定路由器架构位置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:camel="http://camel.apache.org/schema/spring" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <!-- Define your routing rules here --> </camelContext> </beans>
运行时模式位置
在运行时,Apache Camel
不会从
Spring 文件中指定的架构位置下载路由器模式。相反,Apache Camel 会自动从
camel-spring
JAR 文件的根目录获取 schema 的副本。这样可确保用于解析 Spring 文件的 schema 版本始终与当前的运行时版本匹配。这很重要,因为 Apache 网站上发布的模式的最新版本可能与当前使用的运行时版本不匹配。
使用 XML 编辑器
通常,建议您使用全功能 XML 编辑器编辑 Spring 文件。借助 XML 编辑器的自动完成功能,编写符合路由器架构的 XML 更轻松,如果 XML 不正确,编辑器也会立即提醒您。
XML 编辑器
通常
依赖从您在
xsi:schemaLocation
属性中指定的位置下载 schema。为了确保您使用正确的 schema 版本,最好选择
camel-spring.xsd
文件的特定版本。例如,若要为 Apache Camel 的 2.3 版本编辑 Spring 文件,您可以修改 Bean 元素,如下所示:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring-2.3.0.xsd">
编辑完成后,请更改默认值( camel-spring.xsd
)。要查看当前可用于下载的模式版本,请导航至网页 http://camel.apache.org/schema/spring。
1.4. Endpoints
概述
Apache Camel 端点是路由中消息的源和接收器。端点是一个非常一般的构建块:它必须满足的唯一要求是它充当消息来源(制作端点)或作为消息(消费者端点)的接收器(消费者端点)。因此,Apache Camel 中支持各种不同的端点类型,范围从协议支持端点(如 HTTP)到简单的计时器端点,如 Quartz,以固定间隔生成 dummy 消息。Apache Camel 的主要优势之一是,相对容易地添加实施新端点类型的自定义组件。
端点 URI
端点通过 端点 URI 标识,其通用表单如下:
scheme:contextPath[?queryOptions]
URI
方案
标识了协议,如
http
,
contextPath
提供由协议解释的 URI 详情。另外,大多数方案都允许您定义查询选项,而
queryOptions
则采用以下格式指定:
?option01=value01&option02=value02&...
例如,以下 HTTP URI 可以用来连接到 Google 搜索引擎页面:
http://www.google.com
以下文件 URI 可用于读取在
C:\temp\src\data
目录下出现的所有文件:
file://C:/temp/src/data
不是每个 方案 都代表了一个协议。有时候, 方案 只需提供对有用的实用程序(如计时器)的访问。例如,以下计时器端点 URI 每秒生成交换一次(=1000 毫秒)。您可以使用它来调度路由中的活动。
timer://tickTock?period=1000
使用长 Endpoint URI
有时,端点 URI 可能会因为提供的所有配置信息而变得非常长。在 JBoss Fuse 6.2 中,您可以采用两种方法使您使用冗长的 URI 更易于管理。
- 配置端点 9 月
-
您可以单独配置端点,从路由中使用简写 ID 引用端点。
<camelContext ...> <endpoint id="foo" uri="ftp://foo@myserver"> <property name="password" value="secret"/> <property name="recursive" value="true"/> <property name="ftpClient.dataTimeout" value="30000"/> <property name="ftpClient.serverLanguageCode" value="fr"/> </endpoint> <route> <from uri="ref:foo"/> </route> </camelContext>
您还可以在 URI 中配置一些选项,然后使用
property
属性指定附加选项(或覆盖 URI 中的选项)。<endpoint id="foo" uri="ftp://foo@myserver?recursive=true"> <property name="password" value="secret"/> <property name="ftpClient.dataTimeout" value="30000"/> <property name="ftpClient.serverLanguageCode" value="fr"/> </endpoint>
- 跨新行的分割端点配置
-
您可以使用新行分割 URI 属性。
<route> <from uri="ftp://foo@myserver?password=secret& recursive=true&ftpClient.dataTimeout=30000& ftpClientConfig.serverLanguageCode=fr"/> <to uri="bean:doSomething"/> </route>
注意您可以在每行中指定一个或多个选项,每个选项由
&
分隔。
在 URI 中指定时间段
许多 Apache Camel 组件都有选项,其值是时间段(例如,指定超时值等)。默认情况下,此类时间周期选项通常指定为纯数字,被解释为毫秒的时间段。但是,Apache Camel 还支持更易读的语法,它可让您用小时、分钟和秒来表达周期。正式,人类可读的时间段是一个符合以下语法的字符串:
[NHour(h|hour)][NMin(m|minute)][NSec(s|second)]
在方括号
[]
中,每个术语都是可选的,并且符号
(A|B)
表示
A
和
B
是 alternatives。
例如,您可以使用 45
分钟的时间配置计时器
端点,如下所示:
from("timer:foo?period=45m") .to("log:foo");
您还可以使用小时、分钟和第二个单元的任意组合,如下所示:
from("timer:foo?period=1h15m") .to("log:foo"); from("timer:bar?period=2h30s") .to("log:bar"); from("timer:bar?period=3h45m58s") .to("log:bar");
在 URI 选项中指定原始值
默认情况下,您在 URI 中指定的选项值会自动进行 URI 编码。在某些情况下这是不需要的行为。例如,当设置 password 选项时,最好在
没有 URI 编码的情况下
传输原始字符字符串。
通过利用语法指定选项值,可以切换 URI 编码,即
RAW(
RawValue
)
。例如,
from("SourceURI") .to("ftp:[email protected]?password=RAW(se+re?t&23)&binary=true")
在本例中,密码值作为字面值传输,即
se+re?t&23
。
不区分大小写的 enum 选项
某些端点 URI 选项映射到 Java
enum
constants。例如,Log 组件的
level
选项可以采用
enum
值
INFO
、
WARN
、
ERROR
等等。这个类型转换不区分大小写,因此可以使用以下任意一种选项来设置日志制作者端点的日志记录级别:
<to uri="log:foo?level=info"/> <to uri="log:foo?level=INfo"/> <to uri="log:foo?level=InFo"/>
指定 URI 资源
从 Camel 2.17,基于资源组件(如 XSLT)可以使用
ref:
作为前缀从 Registry 加载资源文件。
例如,
如果myvelocityscriptbean
和
mysimplescriptbean
是 registry 中的两个 Bean 的 ID,您可以按照如下所示使用这些 Bean 的内容:
Velocity endpoint: ------------------ from("velocity:ref:myvelocityscriptbean").<rest_of_route>. Language endpoint (for invoking a scripting language): ----------------------------------------------------- from("direct:start") .to("language:simple:ref:mysimplescriptbean") Where Camel implicitly converts the bean to a String.
Apache Camel 组件
每个 URI 方案 都映射到 Apache Camel 组件 ,其中 Apache Camel 组件基本上是一个端点工厂。换句话说,若要使用特定类型的端点,您必须在运行时容器中部署对应的 Apache Camel 组件。例如,若要使用 JMS 端点,您要在容器中部署 JMS 组件。 Apache Camel 提供了大量不同的组件,可让您将应用程序与各种传输协议和第三方产品集成。例如,一些常用的组件有: File、JMS、CXF(Web 服务)、HTTP、Jetty、Direct 和 Mock。有关支持组件的完整列表,请参阅 Apache Camel 组件文档 。 大多数 Apache Camel 组件都单独打包成 Camel 内核。如果您使用 Maven 构建应用程序,只需在相关组件构件上添加依赖项即可向应用程序中添加组件(及其第三方依赖项)。例如,要包含 HTTP 组件,您要将以下 Maven 依赖项添加到项目 POM 文件中:
<!-- Maven POM File --> <properties> <camel-version>{camelFullVersion}</camel-version> </properties> <dependencies> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-http</artifactId> <version>${camel-version}</version> </dependency> </dependencies>
以下组件内置到 Camel 内核(在
camel 内核
工件中),因此始终可用:
dataset
direct
Properties
timer