CamelContext
CamelContext
CamelContext 是运行时系统,它将 Apache Camel 的所有基本概念(路由、端点、组件等)组织在一起。
这个上下文对象代表 Camel 运行时系统。通常,一个应用程序中只有一个 CamelContext 实例。

CamelContext 提供了对许多功能和服务的访问,其中最值得注意的有组件、类型转换器、注册表、端点、路由、数据格式和语言。
下表列出了 CamelContext 提供的最常用服务:
| 服务 | 描述 |
|---|---|
| 组件 | 包含所使用的组件。 |
| 端点 | 包含已经使用过的端点。 |
| 路由 | 正在使用的路由。 |
| 数据格式 | 包含已加载的数据格式。 |
| 语言 | 包含已加载的语言。 |
| 类型转换器 | 包含已加载的类型转换器。Camel 提供了一种机制,允许你手动或自动地将一种类型转换为另一种类型。 |
| 注册表 | 包含一个注册表,允许你查找 bean。 |
CamelContext 基础入门
为了让你更好地理解 Apache Camel,我们将讨论 CamelContext 内部包含的内容。
路由引擎
Camel 的路由引擎在底层传递消息,并承担所有繁重的工作,以确保消息被正确路由。它不会暴露给开发者,但你应该知道它的存在。
路由
路由是 Camel 的核心抽象。定义路由最简单的方式是将其描述为一系列处理器的链。在消息应用中使用路由有很多原因。通过将客户端与服务器、生产者与消费者解耦,路由可以做到以下几点:
- 动态决定客户端将调用哪个服务器
- 提供灵活的方式来添加额外的处理
- 允许客户端和服务器独立开发
- 通过将各司其职的不同系统连接起来,促进更好的设计实践
- 允许对服务器的客户端进行桩替换(使用 mock),以便进行测试
Camel 中的每条路由都有唯一标识符。你可以使用该标识符来进行日志记录、调试、监控以及启动和停止路由。
路由有且只有一个消息输入源。它们实际上绑定到一个输入端点。
领域特定语言(DSL)
为了将处理器和端点连接在一起形成路由,Camel 定义了一种 DSL。
在基于 Java 的 Camel 中,DSL 意味着一个流式 Java API,其中的方法以 EIP 术语命名。Camel 提供了多种 DSL 语言。你也可以使用 XML 和 YAML DSL 来定义同一条路由。
在这里,你只需一条 Java 语句,就能定义一条从 file 端点消费文件的路由。Camel 使用 Filter EIP,通过 XPath 谓词来判断消息是否不是测试订单,从而对消息进行路由。如果消息通过测试,Camel 会将其转发到 JMS 端点。未通过过滤测试的消息将被跳过。
- Java
- XML
- YAML
from("file:data/inbox")
.filter().xpath("/order[not(@test)]")
.to("jms:queue:order");<route>
<from uri="file:data/inbox"/>
<filter>
<xpath>/order[not(@test)]</xpath>
<to uri="jms:queue:order"/>
</filter>
</route>- route:
from:
uri: file:data/inbox
steps:
- filter:
expression:
xpath:
expression: "/order[not(@test)]"
steps:
- to:
uri: jms:queue:orderDSL 为 Camel 用户构建应用提供了一种良好的抽象。不过在底层,路由是由一个处理器(processor)图组成的。
处理器
处理器是 Camel 的核心概念,代表一个能够使用、创建或修改传入交换(Exchange)的节点。
在路由过程中,交换在各个处理器之间流动;因此,你可以把路由看作一个图,其中以各种专用处理器作为节点,用连线将一个处理器的输出连接到另一个处理器的输入。处理器可以是 EIP(企业集成模式)的实现、特定组件的生产者,也可以是你自己编写的代码。下图展示了处理器之间的消息流转。

路由以一个消费者(即 DSL 中的 from)开始,由它填充初始的交换。在每个处理器步骤中,上一步的输出(out)消息就是下一步的输入(in)消息。在许多情况下,处理器并不设置 out 消息,此时会重用 in 消息。交换的交换模式决定了在路由结束时是否需要向调用者返回回复。如果交换模式(MEP)为 InOnly,则不会返回任何回复;如果为 InOut,Camel 会取最后一步的 out 消息并将其返回。
Exchange(交换)
Exchange 是在路由中流动的消息容器。每当消费者接收到消息时,都会将其包装进一个 Exchange,并通过路由的处理器链发送。
Exchange 包含以下内容:
- In 消息 —— 当前正在被处理的消息。大多数处理器直接读取并修改 In 消息。
- 交换属性 —— 作用于该交换的元数据,类型为
Map<String, Object>。属性不会传播到外部系统,它们仅在路由内部可见。可以使用属性在同一路由的各处理器之间传递状态。 - 异常 —— 在处理失败时设置。由错误处理器和异常子句用于确定如何处理该失败。
交换模式(MEP)决定了该交换是单向(InOnly)的还是请求-回复(InOut)的。对于 InOut,Camel 会将最终消息作为回复返回给调用者。
变量
变量(Variables)是路由过程中存储用户数据的推荐方式,可以替代交换属性。
Exchange 属性也会被 Camel 以及部分 EIP 和组件在内部使用,这可能导致命名冲突或意外行为。变量则完全供最终用户使用——Camel 绝不会在内部设置或读取你的变量。
变量可以在不同的层级进行作用域划分:
- Exchange(默认)——当前交换私有,与 Exchange 属性相同,但不会与 Camel 内部实现产生命名冲突
- Route——在特定路由的所有交换之间共享
- Group——在一组命名路由之间共享
- Global——在整个
CamelContext之间共享
变量还可以通过 variableSend 和 variableReceive 选项与常用的 EIP(to、enrich、poll、unmarshal 等)集成,从而无需修改当前消息即可轻松从外部系统收集数据。
完整的参考文档请参阅变量。
消息
消息由三个部分组成:
- Body(消息体)——即负载,可以是任意 Java 类型。Camel 的类型转换器系统会在需要时自动进行类型转换(例如,
String转InputStream、JSON 转 POJO、byte[]转String)。 - Headers(消息头)——一个
Map<String, Object>形式的元数据。生产者和消费者会将消息头在内部与外部系统之间传递。例如,File 组件会设置CamelFileName,HTTP 组件会映射 HTTP 头。Camel 内部使用的消息头以Camel为前缀。 - Attachments(附件)——二进制附件(主要用于邮件和 SOAP 组件)。
| 消息头与 Exchange 属性是不同的。消息头随消息一起传递,可以发送到外部系统。Exchange 属性的作用范围限于路由,永远不会离开 Exchange。 |
|---|
组件
组件是 Camel 中的主要扩展点。
从编程角度来看,组件相当简单:它们与一个名称关联,该名称用于 URI 中,同时它们充当端点的工厂。
例如,FileComponent 在 URI 中通过 file 引用,它会创建 FileEndpoint。端点或许是 Camel 中更为基础的概念。
端点
端点是 Camel 的一种抽象,用于建模系统通过其发送或接收消息的通道末端。

在 Camel 中,你使用 URI 来配置端点,例如 file:data/inbox?delay=5000,并且也通过这种方式引用端点。在运行时,Camel 根据 URI 表示法查找端点。下图展示了其工作原理。

scheme(1)表示由哪个 Camel 组件处理该类型的端点。在此例中,file 这个 scheme 选择了 FileComponent。FileComponent 随后充当工厂,根据 URI 的其余部分创建 FileEndpoint。上下文路径 data/inbox(2)告诉 FileComponent 起始文件夹是 data/inbox。选项 delay=5000(3)表示应以 5 秒的间隔轮询文件。
下图展示了一个端点如何与交换(exchange)、生产者和消费者协同工作。

端点充当工厂,用于创建能够向特定端点接收和发送消息的消费者与生产者。
生产者
生产者(Producer)是 Camel 中的一种抽象,指代能够向端点发送消息的实体。当消息被发送到端点时,生产者负责处理使消息数据与该特定端点兼容的细节。例如,FileProducer 会将消息体写入 java.io.File。而 JmsProducer 会在将消息发送到 JMS 目的地之前,先把 Camel 消息映射为 jakarta.jms.Message。这是 Camel 的一个重要特性,因为它隐藏了与特定传输方式交互的复杂性。你只需要将消息路由到端点,繁重的工作由生产者来完成。
消费者
消费者(Consumer)是接收由某些外部系统产生的消息的服务,它将这些消息包装进一个交换,并发送它们去进行处理。消费者是 Apache Camel 中被路由交换的来源。要创建一个新的交换,消费者会使用包装所消费负载的端点。随后使用处理器通过路由引擎在 Camel 中发起该交换的路由。
Camel 有两种消费者:事件驱动消费者和轮询消费者(或称定时轮询消费者)。这些消费者之间的差异很重要,因为它们用于解决不同的问题。
事件驱动消费者
最常见的消费者是事件驱动消费者,如下所示:

这类消费者主要与客户端-服务器架构和 Web 服务相关。在 EIP(企业集成模式)领域,它也被称为异步接收器。事件驱动的消费者监听特定的消息通道,例如 TCP/IP 端口、JMS 队列、Twitter 账号、Amazon SQS 队列、WebSocket 等等,然后等待客户端向它发送消息。当消息到达时,消费者被唤醒并取出该消息进行处理。
轮询消费者 / 定时轮询消费者
与事件驱动的消费者相反,轮询消费者会主动去特定的来源(例如 FTP 服务器)获取消息。在 EIP 术语中,轮询消费者也被称为同步接收器,因为它在处理完当前消息之前不会继续轮询更多消息。轮询消费者的一种常见变体是定时轮询消费者,它按照预定的时间间隔进行轮询。File、FTP 和邮件组件都使用定时轮询消费者。
在 Camel 组件中,只使用事件驱动消费者或定时轮询消费者。非定时的轮询消费者仅用于按需轮询,例如使用 Poll Enrich EIP 时,或在 Java 中通过 Endpoint 的 createPollingConsumer() 方法创建 PollingConsumer 实例时使用。 |
|---|
启动顺序
CamelContext 启动时,会按照特定的顺序初始化服务:
- CamelContext — 初始化注册表、类型转换器和内部服务
- 组件 — 创建组件实例(或在首次使用时延迟加载)
- 端点 — 解析并创建路由所引用的端点
- 路由 — 将路由定义构建为处理器链
- 消费者 — 消费者最后启动,因此在任何消息流入之前,所有路由、端点和处理器都已完全就绪
这一顺序确保了当第一条消息到达时,它所需的一切都已初始化完毕。消费者最后启动非常重要——这可以防止消息在路由准备好处理它们之前就到达。
可以在运行时使用 CamelContext 或通过 JMX 单独启动和停止路由。
关于完整的生命周期细节(包括挂起/恢复和优雅关闭),请参阅 生命周期。
另请参阅
有关 Apache Camel 的高层架构信息,请参阅以下内容。
评论
登录后参与评论
KnowForge