前言
通过本教程学习 Apache Camel 的基础知识并在 Spring Boot 项目上创建您的第一个 Camel。
想开始使用Apache Camel吗?这是我关于这个流行的 Java 集成框架的教程。
我为完整的初学者编写了这个 Apache Camel 教程。它向您介绍了 Camel 的核心概念,并向您展示了如何使用 Maven 构建和运行您的第一个 Camel 项目,该项目在 Spring Boot 上运行。
欢迎!
欢迎来到这个初学者的 Apache Camel 教程。Apache Camel 是一个非常流行的 Java 集成框架。
有多受欢迎?好吧,Stack Overflow 上的这个问题,Apache Camel 究竟是什么,已经被查看了超过一百万次。
那是巨大的!因此,不仅人们对 Camel 产生了浓厚的兴趣,而且人们也渴望了解它的功能。
您来到这里是因为您想开始使用 Apache Camel 并了解基础知识。
无论您的背景如何,本教程都将帮助您掌握 Apache Camel 的基础知识,并让您快速上手。
享受!
PS:如果你喜欢这个教程,请分享给你的朋友,它有助于传播关于Camel的信息!🐪
你会学到什么
在本教程结束时,您将:
- 了解 Apache Camel 是什么,以及它可以做什么
- 使用 Maven 创建一个基本的 Apache Camel 项目
- 了解 Camel 如何与 Spring Boot 配合使用
- 查看如何使用日志记录
- 运行您的应用程序并对其进行测试
本教程适合您:
- 你想学习Apache Camel
- 您想知道如何创建 Camel 项目
- 您刚刚开始使用Red Hat Fuse并想知道如何构建 Camel 路由
- 您刚开始使用 Talend ESB并想了解基本概念,以便了解中介路由。
- 您是一名 Java 开发人员,并且希望通过一个强大的框架来提升您的技能
- 你是一名建筑师,你想更多地了解 Camel 的含义
您应该有一点 Java 经验,并且熟悉使用命令行。
Apache Camel 简介
apache camel官网:Home - Apache Camel
那么什么是 Apache Camel 以及它的用途是什么?
Apache Camel 是一个Java集成库。它是一组 Java API,可帮助您在不同的计算机系统之间集成和处理数据。
换句话说,骆驼是像不同的应用程序之间的胶水。
Camel 带有200 多个组件,可让您集成许多不同的应用程序。Camel 可以集成从 Web 服务到在磁盘上读写文件的任何内容。您甚至可以将 Camel 与 Twitter、Facebook 和 Salesforce 等网络应用程序连接起来。
您可以将 Apache Camel视为 Java的管道工具包。就像真正的管道一样,Camel 从一个点获取数据,并将其通过管道传输到另一个点。在此过程中,数据可以更改、转换或通过其他管道发送。
您的管道工具包中包含一系列适用于各种不同应用程序和软件系统的适配器。有了一系列可供您使用的工具,您就可以选择如何建造管道了。
Camel 的创意从何而来?
Camel 受到Enterprise Integration Patterns一书的启发,这是一本关于集成软件系统的学术教科书。这本书的作者(现在被认为是“经典”!)采用了许多常见的集成用例,将它们提炼成可重用的模式并记录下来。书中描述了每种模式,在某些情况下,还有一些示例代码。
Camel 开发人员认为构建一个代表本书理想的 Java 框架是一个好主意。因此 Apache Camel 大量借鉴了本书。
Camel事实
希望您已经开始了解 Camel 是什么。
以下是有关 Camel 的一些事实,可帮助您了解有关项目本身的更多信息:
- 它是 用 Java 构建的——这可能看起来很明显,但是一旦你理解了这一点,你就会发现你可以使用 Java 的全部功能
- 整个代码是完全开源的——在 Github 上查看——没有什么隐藏在昂贵的闭源产品后面。您可以为项目做出贡献并回馈社区。(您不必成为编码员即可做出贡献)
- 它 不仅适用于 Web 服务——它还是一个通用的集成框架。这意味着您可以选择使用 Camel 来构建与 Web 服务相关的内容,但您不必这样做。
- 它带有一个 庞大的组件库——如果你能想到一个你想要与之交互的系统,那么可能已经有人为它编写了一个组件;您可以做任何事情,从推送文件到 AWS到发送推文。
- 它已经 成熟——Apache Camel 是一些商业集成产品的基础,如Red Hat Fuse和Talend ESB。在这些公司工作的工程师将代码贡献回开源 Camel 项目,以使其对每个人都更好。
Camel 的常见用例
几乎任何时候您需要将数据从A移动到B,您都可以使用 Camel。可以使用Camel实现以下任何场景:
- 从 FTP 服务器获取发票并将其通过电子邮件发送到您的会计部门
- 从文件夹中提取文件并将其推送到 Google Drive
- 从ActiveMQ 队列中获取消息并将它们发送到 Web 服务
- 制作允许用户从数据库中检索客户详细信息的 Web 服务
这些只是几个例子。有了 Camel 中可用的各种组件,天空就是极限。
为什么使用 Camel
1 ,我们要解决的问题以及解决方案
我们要解决的问题
- 完成组织内外的各种异构系统、应用、数据源之间共享和交换信息。
- 优化现有结构,使整个系统易于拓展和维护。
- 保证多个系统各自独立互不干扰。
总结发现我们实际要解决的问题是:企业应用集成(Enterprise Application Integration,EAI) 是完成在组织内、外的各种异构系统,应用和数据源之间共享和交换信息和协作的途径,方法学,标准和技术。
2,EAI的常用解决方案
SOA(Service Oriented Architecture) 中文释义为 “面向服务的架构”它是一种设计理念,其中包含多个服务, 服务之间通过相互依赖最终提供一系列完整的功能。各个服务通常以独立的形式部署运行,服务之间通过网络进行调用。要求各个服务遵循统一的规范和契约。
ESB企业服务总线
ESB(Enterprise Service Bus,即企业服务总线) 就是一根管道,用来连接各个服务节点。ESB的存在是为了集成基于不同协议的不同服务,ESB 做了消息的转化、解释以及路由的工作,以此来让不同的服务互联互通
3,如何实现ESB
当前实现ESB比较成熟的模型为EIP(Enterprise Integration Patterns)1。他的包含如下规范:
- 集成方式(Integration Styles):EIP规定所有集成模式要基于消息传送模式。
- 通道模式(Channel Patterns):消息通过通道进行传递。
- 消息体模式(Message Construction Patterns):描述了在消息系统中交互的消息的规范。
- 路由模式(Routing Patterns):消息如何从发送者分发到正确的接收者,中间一般不进行修改。
- 转换模式(Transformation Patterns):将消息体的内容修改为接收者可以理解的结构,中间可能要对数据进行修改或者筛选。
- 终端模式(Endpoint Patterns):生成或者接收消息的客户。
- 系统管理模式(System Management Patterns):提供监控整个系统状态的工具,包括错误处理,压力测试或者监控系统变化。
Camel概念解释
Camel 就是企业信息集成框架,它提供了很多简单好用而又强大的组件,用户可以根据场景来选择不同的EIP(企业集成模式)来实现自己的需求,以响应快速变化的业务。可以把它当成企业信息总线(ESB)的轻量级实现。
你如何像骆驼一样思考?下图显示了 Camel 中的一些核心概念。
可视化骆驼路线
在本节中,我将依次查看每一个:
Route
在骆驼最基本的概念是route。路由是您在 Camel 中配置的对象,它将您的数据从A移动到 B。
使用前面的管道示例,Route是将数据从一个地方移动到另一个地方的管道。它在称为Endpoints事物之间移动数据。
您可以使用 Java 语法或 XML 语法在 Camel 中创建路由。这是一个用 Java 语法编写的非常简单的路由。这会将文件从一个文件夹移动到另一个文件夹:
// 这是一个完整的 Camel 路由定义!
// Camel 将文件从一个文件夹移动到另一个文件夹
from("file:home/customers/new").to("file:home/customers/old");
Routing路由条件
在控制端点和处理器之间、处理器和处理器之间,Camel允许开发人员进行路由条件设置。例如开发人员可以拥有当Exchange In Message的内容为A的情况下将消息送入下一个处理器A,当Exchange In Message的内容为B时将消息送入下一个处理器B的处理能力。又例如,无论编排的路由中上一个元素的处理消息如何,都将携带消息的Exchange对象 复制 多份,分别送入下一处理器X、Y、Z。开发人员甚至还可以通过路由规则完成Exchange到多个Endpoint的负载传输。
Camel中支持的路由规则非常丰富,包括:Message Filter、Based Router、Dynamic Router、Splitter、Aggregator、Resequencer等等。在Camel的官方文档中使用了非常形象化的图形来表示这些路由功能(Enterprise Integration Patterns :: Apache Camel):
Endpoints
在 Camel 中,endpoint是一个接口,Camel 通过它与另一个系统交换消息。Camel 可以从端点接收消息,也可以向端点发送消息。
端点是路线中沿途的步骤。您可以通过几种不同的方式声明它们,但最常见的方法是使用类似于 URI 的语法来声明它们,如下所示:
prefix:mainpart?option1=xxx&option2=xxx...
…prefix 端点引用的组件在哪里,是 mainpart 端点需要的一些配置。
例如:在路由的开始处,Camel 收到来自端点的消息。如果此端点为 file:/myfolder,则 Camel 将使用 File 组件读取 /myfolder.
Components
为了让 Camel 创建端点,它附带了一个组件库。组件就像一个插件,允许您连接到外部系统,
例如: 磁盘上的文件、邮箱或 Dropbox 或 Twitter 等应用程序。
您可以将组件视为创建端点的工厂。
每当您需要将数据放入或取出应用程序时,您可能会发现已经存在一个 Camel 组件来为您完成这项工作。这意味着您无需浪费时间编写自己的代码来读取文件或调用 Web 服务。您只需找到您需要的组件并使用它。
Camel 组件是可重用的、开源的,您甚至可以贡献自己的组件。以下是一些最常见的组件,以及如何在端点中引用它们:
Component |
目的 |
端点 URI |
HTTP |
用于创建或使用网站 |
http: |
File |
用于读取和写入文件 |
file: |
JMS |
用于读取和写入 |
jms: |
Direct |
一起 direct是基于内存的同步消息组件 使用Direct组件,生产者直接调用消费者。因此使用Direct组件的唯一开销是方法调用 |
direct: |
Salesforce |
用于将数据传入和传出 Salesforce |
salesforce: |
可以看到,每个组件通常都可以读写:
- 配置为写入内容的组件称为生产者——例如,写入磁盘上的文件,或写入消息队列。
- 配置为读取某些内容的组件称为使用者——例如,从磁盘读取文件,或接收 REST 请求。
在每个端点之间,还可以通过将数据传递到另一个端点或使用 EIP 来转换或修改数据。
企业集成模式 (EIP)
EIP是 Camel 的另一个重要组成部分。它们根据我之前提到的《企业集成模式》一书中定义的模式对消息进行特殊处理。
当您想对消息执行一些常见活动时,例如转换、拆分和日志记录,您将使用 EIP。以下是 Camel 中一些常见的 EIP:
EIP名称 |
它能做什么 |
Java语法 |
Splitter |
将消息拆分为多个部分 |
.split() |
Aggregator |
将多条消息合并为一条消息 |
.aggregate() |
Log |
写一条简单的日志消息 |
.log() |
Marshal |
将对象转换为文本或二进制格式 |
.marshal() |
From |
从端点接收消息 |
.from() |
To |
向端点发送消息 |
.to() |
(是的,from 和 to 也是 EIP!)
From 端点类型
Apache Camel 提供了丰富的 from 端点,适用于不同的消息来源和场景。选择合适的端点可以优化消息处理的效率和灵活性。
例如:
- 自动触发:使用 timer、file、jms 等端点。
- 手动触发:使用 direct 端点,通过代码调用。
端点类型 |
描述 |
触发方式 |
典型用途 |
示例 |
Timer |
定时触发消息,类似定时任务。 |
自动触发 |
周期性任务,如每分钟检查数据。 |
from("timer:myTimer?period=1000") |
File |
监听指定目录,文件出现或更新时触发。 |
自动触发 |
文件处理,如读取目录中的文件。 |
from("file:input?noop=true") |
Direct |
内存中的端点,用于同一 JVM 内的路由间通信。 |
手动触发 |
手动触发消息的路由,如代码调用。 |
from("direct:start") |
Seda |
内存队列,异步处理消息。 |
手动触发 |
异步调用,如解耦路由处理。 |
from("seda:queue") |
Jms |
与 JMS 消息队列集成。 |
自动/手动 |
消息队列,如 ActiveMQ、IBM MQ。 |
from("jms:queue:myQueue") |
Kafka |
与 Kafka 消息队列集成。 |
自动/手动 |
高吞吐量消息处理。 |
from("kafka:myTopic") |
Http |
监听 HTTP 请求。 |
自动触发 |
RESTful 服务,如 API 接口。 |
from("jetty:http://0.0.0.0:8080/myapp") |
Mqtt |
与 MQTT 协议集成。 |
自动/手动 |
物联网设备通信。 |
from("mqtt:topic?subscriptionQos=1") |
ActiveMQ |
与 ActiveMQ 消息队列集成。 |
自动/手动 |
企业级消息传递。 |
from("activemq:queue:myQueue") |
FTP/SFTP |
监听 FTP/SFTP 服务器,处理文件传输。 |
自动触发 |
文件传输,如从 FTP 服务器获取文件。 |
from("ftp://user:password@host/path") |
CouchDB |
与 CouchDB 数据库集成。 |
自动/手动 |
NoSQL 数据库操作。 |
from("couchdb:myDatabase") |
SQL |
执行 SQL 查询。 |
自动/手动 |
数据库操作,如查询或更新。 |
from("sql:select * from users") |
Main |
启动 Camel 应用并监听指定端点。 |
自动触发 |
Camel 应用启动时自动运行的路由。 |
from("main:myRoute") |
Log |
记录日志信息。 |
手动触发 |
日志记录,如调试信息输出。 |
from("log:myLog") |
Mock |
模拟端点,用于测试。 |
手动触发 |
单元测试,如验证消息流转。 |
from("mock:result") |
1. Timer 端点
- 功能:定时触发消息,类似于定时任务。
- 使用场景:需要周期性执行的任务,例如每分钟检查一次数据。
- 示例:
from("timer:myTimer?period=1000") // 每秒触发一次
.to("direct:processData");
- 特点:可以配置触发频率(如 period)或使用 Cron 表达式。
2. File 端点
- 功能:监听指定目录,当有文件出现或更新时触发消息。
- 使用场景:文件处理任务,例如从指定目录读取文件并解析内容。
- 示例:
from("file:input?noop=true") // 监听 input 目录,不删除文件
.to("direct:processFile");
- 特点:支持监听目录、过滤文件名、是否删除文件等选项。
3. Direct 端点
- 功能:内存中的端点,用于同一 JVM 内的路由间通信。
- 使用场景:需要手动触发消息的路由,例如通过代码调用。
- 示例:
from("direct:start")
.to("direct:nextStep");
- 特点:需要手动调用 ProducerTemplate 发送消息,同步执行。
4. SEDA 端点
- 功能:基于内存队列的异步端点,适用于线程池处理。
- 使用场景:需要异步处理消息的路由,例如高并发场景。
- 示例:
from("seda:myQueue")
.to("direct:processQueue");
- 特点:支持线程池,消息处理不阻塞调用方。
5. VM 端点
- 功能:类似于 SEDA,但允许跨多个 Camel 应用通信。
- 使用场景:需要跨 JVM 实例的路由通信。
- 示例:
from("vm:myQueue")
.to("direct:processVm");
- 特点:支持跨 JVM,但需确保所有实例使用相同的 VM 端点名称。
6. JMS 端点
- 功能:与 Java 消息服务(JMS)集成,用于消息队列或主题。
- 使用场景:分布式系统中的消息传递,例如订单处理。
- 示例:
from("jms:queue:orderQueue")
.to("direct:processOrder");
- 特点:支持队列和主题,需要 JMS 提供者(如 ActiveMQ)。
7. HTTP 端点
- 功能:监听 HTTP 请求,处理 Web 服务调用。
- 使用场景:REST API 或 SOAP 服务。
- 示例:
from("http://localhost:8080/api")
.to("direct:processHttp");
- 特点:支持 GET、POST 等多种 HTTP 方法。
8. Quartz 端点
- 功能:基于 Quartz 定时器的高级定时任务。
- 使用场景:复杂的定时任务,例如基于 Cron 表达式的调度。
- 示例:
from("quartz://report?cron=0 0 9 * * ?") // 每天早上 9 点触发
.to("direct:processDailyReport");
- 特点:支持更复杂的调度逻辑。
9. FTP 端点
- 功能:监听 FTP 服务器,处理文件传输。
- 使用场景:需要从 FTP 服务器获取或上传文件。
- 示例:
from("ftp://user:password@host/path?noop=true")
.to("direct:processFtpFile");
- 特点:支持文件过滤、是否删除文件等选项。
10. ActiveMQ 端点
- 功能:与 ActiveMQ 消息队列集成。
- 使用场景:需要高可靠性的消息传递。
- 示例:
from("activemq:queue:highPriority")
.to("direct:processHighPriority");
- 特点:支持事务和持久化。
Direct 端点
在 Apache Camel 中, direct 端点用于同步调用,确保消息从一个路由直接传递到另一个路由。您提到的场景涉及从一个 .to("direct:pro_pre_CommonSDR_csl") 跳转到另一个 from("direct:pro_pre_CommonSDR_csl") 定义的独立路由。
详细解析和实现方式:
1. direct 端点的特性
- 同步调用:direct 端点会阻塞当前线程,直到目标路由处理完成。
- 路由隔离:.to("direct:xxx") 是一个路由片段,而 from("direct:xxx") 是一个独立路由的入口。
2. 跳转逻辑实现
- 路由 A:包含 .to("direct:pro_pre_CommonSDR_csl")。
- 路由 B:以 from("direct:pro_pre_CommonSDR_csl") 开头。
XML DSL 示例
<camelContext xmlns="http://camel.apache.org/schema/spring">
<!-- 路由 A -->
<route>
<from uri="direct:start"/>
<log message="Processing in Route A"/>
<to uri="direct:pro_pre_CommonSDR_csl"/> <!-- 跳转到路由 B -->
<log message="Continuing in Route A after B"/>
</route>
<!-- 路由 B -->
<route>
<from uri="direct:pro_pre_CommonSDR_csl"/>
<log message="Processing in Route B"/>
<to uri="mock:resultB"/>
</route>
</camelContext>
Java DSL 示例
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;
@Component
public class MyRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
// 路由 A
from("direct:start")
.log("Processing in Route A")
.to("direct:pro_pre_CommonSDR_csl") // 跳转到路由 B
.log("Continuing in Route A after B");
// 路由 B
from("direct:pro_pre_CommonSDR_csl")
.log("Processing in Route B")
.to("mock:resultB");
}
}
3. 关键点说明
- 路由 B 的独立性:
- from("direct:pro_pre_CommonSDR_csl") 是一个独立的路由入口,可以单独触发(例如通过 template.sendBody("direct:pro_pre_CommonSDR_csl", "test"))。
- 当路由 A 调用 to("direct:pro_pre_CommonSDR_csl") 时,消息会同步传递到路由 B。
- 消息传递流程
- 路由 A → log → to("direct:pro_pre_CommonSDR_csl") → 阻塞等待路由 B 完成 → log(继续路由 A)。
- 路由 B → log → to("mock:resultB") → 返回路由 A。
- 调试建议
- 在路由 B 的 log 中添加唯一标识(如 log.message("Route B received: ${body}")),确保消息正确传递。
- 使用 CamelContext.createProducerTemplate() 手动触发路由 B,验证其独立性。
4. 常见问题排查
- 问题:跳转后无日志输出。
- 问题:路由 A 未继续执行。
为什么 路由 A 会跑到路由B ?
- direct 端点的同步特性
- 当你在路由 A 中使用 时,这并不是让当前线程(执行路由 A 的线程)停下来等待。相反,它告诉 Camel:“请将当前的消息(Exchange)发送到名为 propreCommonSDRcsl 的端点,并且我(路由 A)要等待这个端点处理完成后再继续执行。”
- direct 端点的设计就是为了同步消息传递。它就像一个直接的函数调用,调用者(路由 A)会等待被调用者(路由 B)执行完毕。
- 路由 B 是 direct 端点的目标
- 你定义了另一个路由,它的入口就是 。这表示这个路由 B 是专门用来处理发送到 direct:propreCommonSDRcsl 端点的消息的。
- 当路由 A 执行到 时,Camel 内部会找到这个入口为 direct:propreCommonSDRcsl 的路由 B。
- 消息的传递与处理
- Camel 会将路由 A 当前处理的消息(包含 body、headers、exchange attributes 等)复制一份(或传递引用,取决于配置,但行为上表现为独立处理),发送给路由 B 的入口。
- 路由 B 开始执行其定义的步骤(比如你的 和 )。
- 路由 B 处理完消息后,会将其传递给下一个组件(在这里是 mock:result)。对于 direct 端点,处理“完成”通常意味着消息已经传递到了下一个组件(或者路由结束)。
- 路由 A 的继续执行
- 因为 是一个同步调用,路由 A 的线程会一直阻塞,直到路由 B 处理完成。
- 一旦路由 B 处理完成,Camel 就会通知路由 A:“目标端点 direct:propreCommonSDRcsl 已经处理完了。”
- 然后,路由 A 就会继续执行 之后的步骤(比如你的 )。
简单类比:
想象一下你在写一个程序:
// 路由 A
public void processA() {
System.out.println("Starting Route A");
// ... 一些处理 ...
// 调用另一个方法
processB();
// ... 路由 A 的后续处理 ...
System.out.println("Continuing Route A after B");
}
// 路由 B
public void processB() {
System.out.println("Hello from Camel! 1 (Inside Route B)");
// ... 一些处理 ...
}
// 主程序
public static void main(String[] args) {
MyCamelApp app = new MyCamelApp();
app.processA();
}
在这个 Java 例子中,processA 执行到 processB 时,会暂停自己的执行,跳转到 processB 去执行。processB 执行完毕后,控制权会回到 processA,继续执行 processB 之后的代码。
总结:
路由 A 之所以会“跑到”路由 B,是因为 是一个同步调用。它强制路由 A 的执行流程暂停,并将消息传递给 direct:propreCommonSDRcsl 对应的入口(即路由 B),等待路由 B 处理完成后再继续路由 A 的后续步骤。路由 B 就是处理 direct:propreCommonSDRcsl 端点消息的那个独立路由。
在这里 路由B 的 路由名(pro_pre_CommonSDR_csl)?
- < from >标签的作用:它定义了一个路由的起点。Camel 服务器启动后,会监听这个指定的端点,当有消息发送到这个端点时,就会触发这个路由的执行。
- direct:前缀:这表明这个端点是一个Direct Endpoint。Direct Endpoint 的特点是同步处理消息,并且通常用于路由之间的直接、同步调用。
- pro_pre_CommonSDR_csl 部分:这是你为这个特定的 direct 端点起的名字。这个名字的作用是:
- 唯一标识:在同一个 Camel Context(即你的 Spring 应用上下文中)里,这个名字必须是唯一的,用来区分不同的 direct 端点。
- 路由入口:它定义了哪个路由应该处理发送到这个特定 direct 端点的消息。换句话说,< from uri="direct:pro_pre_CommonSDR_csl" /> 这行代码声明了:“如果任何地方通过 to("direct:pro_pre_CommonSDR_csl") 发送消息,那么这个路由(即包含 < from... > 的整个 XML 片段)就会被执行。”
- 你有一个房间(路由 B 的处理逻辑)。
- 这个房间有一个唯一的门牌号(pro_pre_CommonSDR_csl)。
- < from uri="direct:pro_pre_CommonSDR_csl" /> 就像是声明:“如果有人按这个门牌号的门铃(通过 to("direct:pro_pre_CommonSDR_csl")),就请打开这个房间的门,并执行房间里的所有操作。”
Camel Context
最后,为了运行和管理你的路由,Camel 有一个名为 Camel Context 的容器。您的路线在此引擎内运行。你几乎可以把它想象成一个迷你应用服务器。
当 Camel启动时,它会读取您的路由定义(在 Java 或 XML 中),创建路由,将它们添加到 Camel 上下文,并启动 Camel 上下文。
当 Camel终止时,它会关闭您的路由,并关闭 Camel 上下文。
Route是什么样的?
所以。现在您知道,当您在 Camel 中进行开发时,您会使用组件创建在端点之间移动数据的路由。
通过查看一些代码可能最容易理解所有这些,对吗?
尽管 Camel 是 Java 库,但可以使用两种语言之一进行配置 - Java或XML。用骆驼的话说,这些被称为DSL(领域特定语言)。
每条路线开始于from,具有URI,它定义了数据来自哪里。
一条路线可以由多个步骤组成——例如转换数据或记录数据。但路由通常结束于to步骤,其描述数据将被传递to哪里。
Camel 的 Java DSL 中一个非常简单的路由可能如下所示:
from("file:home/customers/new")
.to("file:home/customers/old");
在此示例中,我们使用File 组件(由file:前缀标识)将文件customers/new夹中的所有传入文件移动到该customers/old文件夹。
上面的相同路径可以用 Camel 的 XML DSL 表示,如下所示:
<route>
<from uri="file:home/customers/new"/>
<to uri="file:home/customers/old"/>
</route>
但是......如果我们想在我们的路线中添加另一个步骤怎么办?假设我们想在收到文件时记录一条消息。然后我们只需要在现有步骤之间添加我们的新步骤。像这样:
from("file:home/customers/new")
.log("Received a new customer!")
.to("file:home/customers/old");
在上面的代码中,一条消息从新文件夹移动到旧文件夹。在中间,我们使用名为 的企业集成模式 (EIP) log,它将简单的日志消息写入控制台。
在 XML DSL 中,它看起来像这样:
<route>
<from uri="file:home/customers/new"/>
<log message="Received a new customer!"/>
<to uri="file:home/customers/old"/>
</route>
现在您知道路由的样子了,让我们快速看看数据如何流经路由。
Camel中的数据是什么样的?
骆驼的消息模型
Camel 将数据视为单独的消息——就像通过邮局对信件进行分类一样。
每条消息都是一个单独的对象。一条消息可以很大,也可以很小。Camel 有一个对象来表示消息,它被称为Message.
A Message有一个 body,其中包含消息内容。它还具有标头,可用于保存与消息关联的值。该Message对象然后沿 Route 传递。
A Message是另一个名为 Exchange 的 Camel 对象的一部分。您会经常看到 Camel 文档中提到的术语 Exchange。Exchange 只是当前在 Camel 路由中发生的消息或交互。
了解 Camel 消息模型的重要一点是消息体可以包含几乎任何类型的 Java 对象,例如List、Map或String。正文不必是字符串,如 JSON 或 XML。
Camel不同体型的例子
当您开始使用这些不同类型的对象时,Camel的真正力量就变得显而易见了。Camel 具有强大的内置支持,可以在常见对象类型之间进行转换。
事实上,对于许多常见的文件类型,您甚至可能几乎不需要编写任何转换代码。(减少编写样板代码的时间?听起来不错,不是吗?)
随着您对 Camel 的体验越来越多,您将了解更多关于 Camel 的消息模型的知识!
你的第一个Camel项目
在教程的这一部分中,我将向您展示如何使用 Maven 创建一个新的 Apache Camel 项目,即使您以前从未使用过 Camel。到本节结束时,您将已经创建并运行第一个项目,并开始了解 Camel 的强大功能。
我们将使用Maven 原型来做到这一点。Maven 原型就像新 Java 项目的模板。Camel 在每个版本中都提供了很多。这使您可以轻松开始新项目。
对于本教程,您将需要:
- Java 开发工具包 (JDK)
- Apache Maven
Mac 用户注意事项:如果您使用的是 Mac,我建议您使用 Homebrew 包管理器来帮助您安装 Maven。按照 http://brew.sh 上的说明进行安装。然后,安装 Homebrew 后,通过 brew install maven从终端窗口键入来安装 Maven 。
使用 Maven 创建 Camel 项目
- 从您的桌面,拖放到终端或命令提示符。
- 键入此命令(全部在一行上):
mvn archetype:generate -DarchetypeGroupId=org.apache.camel.archetypes -DarchetypeArtifactId=camel-archetype-spring-boot -DarchetypeVersion=3.4.0
- 然后在出现提示时回答问题:
- 定义属性“groupId”的值:com.example
- 定义属性“artifactId”的值:my-camel-app
- 定义属性 'version' 1.0-SNAPSHOT 的值:(输入 Enter)
- 定义属性 'package' com.example 的值:(输入 Enter)
- 最后,系统会提示您确认、输入 Y 并按 Enter。
Maven 现在将创建您的新 Camel 项目。完成后,您会在新目录中找到它
my-camel-app
看项目内部
从 camel-archetype-spring-boot 原型(v3.4.0)创建的Camel 项目将具有如下所示的文件夹结构:
my-camel-app
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ ├── MySpringBean.java
│ │ ├── MySpringBootApplication.java
│ │ └── MySpringBootRouter.java
│ └── resources
│ ├── application.properties
│ └── META-INF
│ ├── LICENSE.txt
│ └── NOTICE.txt
└── test
├── java
│ └── com
│ └── example
└── resources
RouteBuilder 类
有趣的代码在MySpringBootRouter.java 中。这是一个RouteBuilderclass,这是您定义 Camel 路线的地方。Maven 原型包括一个示例路线,以帮助您入门:
package com.example;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;
@Component
public class MySpringBootRouter extends RouteBuilder {
@Override
public void configure() {
from("timer:hello?period=").routeId("hello")
.transform().method("myBean", "saySomething")
.filter(simple("${body} contains 'foo'"))
.to("log:foo")
.end()
.to("stream:out");
}
}
在这里,您将路由定义添加到 configure() 描述您希望 Camel 创建的每条路由的方法中。
如果您查看代码,您会看到 MyRouteBuilder 该类已经在其中定义了一个路由。
我们将很快查看路线。
utility类
Camel 路线取决于另一个类。在 Camel 路由中,使用 identifier 引用 bean(Java 对象)"myBean"。这实际上是通过在 Spring 上下文 中查找具有 ID 的任何 bean 来解决的 myBean。这意味着它实际上意味着这个类,MySpringBean:
@Component("myBean")
public class MySpringBean {
@Value("${greeting}")
private String say;
public String saySomething() {
return say;
}
}
包含此实用程序类是为了向您展示如何从 Camel 路由调用 Java 代码。该类有一个saySomething() Camel 路由调用的方法。我们很快就会看到这一点。
bootstrap 类
为方便起见,该项目还包含另一个 Java 类 ,MySpringBootApplication 用于引导和运行应用程序。这是一个标准的 Spring Boot 主类:
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MySpringBootApplication {
/**
* A main method to start this application.
*/
public static void main(String[] args) {
SpringApplication.run(MySpringBootApplication.class, args);
}
}
现在让我们看一下代码,看看这个项目做了什么。
项目是做什么的?
演示项目使用以下代码定义路由。代码以特殊的 Camel 语法或DSL(域特定语言)给出:
from("timer:hello?period=")
.routeId("hello")
.transform()
.method("myBean", "saySomething")
.filter(simple("${body} contains 'foo'"))
.to("log:foo")
.end()
.to("stream:out");
这段代码看起来很复杂,但它实际上只是生成消息并打印出来。
让我们详细看看路线的每个部分:
- 它使用计时器 ( timer:...) 来启动路线。Camel 的 Timer 组件可用于以特定时间间隔触发路由。这里,间隔是timer.period,这是文件中定义的属性 application.properties:
这展示了如何在 Camel 路由中使用 Spring Boot 属性。from("timer:hello?period=")
- 该 transform() EIP 指出,我们要改变消息的内容。在此示例中,我们使用 bean() 方法,该方法调用 Java bean(Java 类)上的方法。
.transform().method("myBean", "saySomething")
- Camel 在名为 bean 的注册表中查找 myBean。因为我们使用的是 Spring Boot,它会在 Spring 上下文中搜索 bean 并找到它,因为 MySpringBean 该类是用@Component("myBean").
- Camel 调用该 saySomethingbean 上的方法。
- 的filter()EIP告诉Camel过滤消息,基于一些表达。在这种情况下,我们使用 Camel 的简单表达式语言来检查消息正文是否包含“foo”。如果是这样,我们将当前的交换转储到日志中。
.filter(simple("${body} contains 'foo'")) .to("log:foo") .end()
- 最后,将消息体的内容写入输出流(即标准输出或 STDOUT):
.to("stream:out")
现在让我们运行路由,看看会发生什么。
运行 Camel 应用程序
让我们运行应用程序。我们将使用 Maven 运行它。
从终端或命令提示符运行 Maven,spring-boot:run目标是:
mvn clean spring-boot:run
这将编译您的应用程序并使用Spring Boot Maven 插件来运行您的应用程序。
如果您想从 Eclipse 或 IntelliJ 内部运行此项目,只需为该项目创建一个新的 Maven运行配置,并将其配置为执行目标:spring-boot:run.
当应用程序启动时,您会看到日志如下所示:
来自我们的 Camel 应用程序的日志
上面的日志告诉我们 Apache Camel 已正确启动。
然后,每隔几秒钟,您应该会在日志中看到文本Hello World。这是因为 Camel 每隔几秒钟就会触发要执行的路由。
当路由执行时,消息体被转换(设置为Hello world),然后写入标准输出流或控制台。
要结束应用程序,您只需按 Ctrl+C。
如何使用 Camel 创建 REST 服务?
您现在可能已经知道 Camel 是一个用于在不同系统之间进行集成的框架。它通常不会自己做一些事情,而是创建和配置一些实际完成工作的东西(例如一个组件)。
在 Camel 中创建 REST 服务遵循几乎相同的模式。为 Camel 编写一些说明,它将使用一堆其他组件为您公开您的 REST 服务。您只需要准确选择您希望服务实现的方式,Camel 将负责配置。
这意味着使用 Camel 创建 REST 服务有无数种不同的方式。因此,我不会涵盖每一种不同的方法,而只是简要提及您可以在 Apache Camel 中使用 REST 服务的主要方法。你可以:
- 使用 Camel 支持的组件之一公开一个 REST 服务: 您使用 Camel 的 REST DSL 或 REST 组件定义您的 REST 服务操作,并选择一个将被配置为实现您的服务的组件。然后,Camel 将使用该信息来引导组件、创建您的服务及其操作、将其部署到 Web 服务器(如 Jetty 或 Undertow)中,并为您生成 Swagger/OpenAPI 文档。(这非常简单,这就是我将在本教程中介绍的方式。)
- 使用 Camel 来引导使用 JAX-RS 的服务:Camel 与 Apache CXF 紧密集成,这是 Java 的Web 服务JAX-RS 规范的一种实现。因此,如果您正在考虑使用 JAX-RS 标准来定义您的 REST 服务,那么您可以使用 Camel 使用 CXF 为您引导您的服务。查看CXFRS 组件以获取更多信息。
- 使用 Camel 为现有的 REST 服务提供业务逻辑:如果您已经在应用程序的其他地方公开了 REST 服务 —— 例如使用JAX-RS或 Spring Rest —— 那么您可以使用 Camel 来实现实际的业务逻辑,如果你喜欢。
例如,您可能已经编写了一个包含使用 javax.ws.rs 注释(@Path、@GET、@POST等)注释的方法的服务类,并且已经配置了您的实现(例如 CXF、Jersey 或 Resteasy)。如果是这样,那么在您的服务方法中,您可以使用 Camel 的 Java API(ProducerTemplate 等)将消息发送到 Camel 路由,然后使用来自 Camel 的响应传递回您的使用者。
但在本教程中,我将向您展示我的首选方法。我们将使用 Camel 的 REST DSL 来配置服务并将其部署到嵌入式 Web 服务器中,该服务器在 Spring Boot 中运行。
使用 REST DSL 创建 REST 服务
那么如何在 Camel 中定义 REST 服务呢?最好的方法是使用 REST DSL。
REST DSL 是 Camel 现有路由构建语法的扩展,但专门用于描述 REST 服务。编写和配置很容易。
在幕后,Camel 使用您的 REST DSL 代码来配置实际提供REST 服务的底层组件。您现在不需要担心这些细节,因为 Camel 会为您设置大部分默认值。
REST DSL 可以轻松定义 REST 服务,而无需了解太多底层细节或任何复杂的布线。
在非常高的层次上,当使用 Camel 创建 REST 服务时,我们需要做以下事情:
- 声明我们的 RESTful 服务的端点和操作
- 选择哪个组件将实现该服务(有关支持的组件列表,请参见下文)
- 添加代码以使用参数
- 添加配置以获取 Camel 以帮助我们处理 JSON 或 XML。
定义endpoints端点和操作
为了定义我们服务的操作,我们可以使用 REST DSL 语法。Camel在 Camel 2.14 中引入了REST DSL。REST DSL 基本上是用于定义 REST 服务的 Camel 语法。
看起来有点像普通的 Camel route…… 除了它以rest(). 定义您使用的服务,rest(...) 然后是您的操作,其采用 HTTP 动词的形式,例如 .get() 和 .post() 等。
在 Java DSL 中,它看起来像这样:
rest("/api/customers")
.get()
.route()
.to("direct:getCustomers")
.post()
.route()
.to("file:output/customers");
在 Camel 的 XML DSL 中:
<rest path="/api/customers">
<get>
<route>
<to uri="direct:getCustomers"/>
</route>
</get>
<post>
<route>
<to uri="file:output/customers"/>
</route>
</post>
</rest>
REST 消费者还是 REST 生产者?当 Camel 公开或提供 REST 服务时,Camel 使用术语consumer,因为 Camel 正在通过 REST 消费提供给它的数据。另一方面,REST生产者是 Camel 消费或调用外部 REST 服务的地方。
配置实现
现在我们需要设置一些关于服务本身的信息。我们需要选择哪个组件将实现服务,并设置任何属性,如主机名和端口。
第一件事是选择 Camel 应该引导哪个组件来实现您的 REST 服务。在这里,您可以选择:
- servlet
- spark-rest
- netty-http
- jetty
选择哪个组件完全取决于您,但是对于 Spring Boot 应用程序,我会选择servlet,因为您已经拥有一个 Camel 可以用于 servlet (Tomcat) 的嵌入式 Web 服务器。
然后您可以在 restConfiguration() 块中设置此配置,如下所示:
// 定义实现组件 - 并接受默认主机和端口
restConfiguration().component("servlet");
// 定义组件和主机名和端口
restConfiguration().component("servlet")
.host("localhost").port(8080);
使用参数
您的 REST API 可能需要接受来自使用者的参数。无论您是在正文、URL 还是在查询字符串中使用参数,都可以轻松做到这一点。
POST 正文
像POST这样的操作很容易。请求的正文将存储在 Camel Exchange Body 中。所以你可以像这样访问它:
rest("/customers")
.post().log("The body is ${body}!");
网址参数
当您需要从 URL 中读取参数(例如客户 ID 或产品 ID)时,您需要:
- 在您的操作的 URI 中定义一个占位符,例如 /customers/{id}
- 稍后获取您的输入,使用同名的Header - 例如 ${header.id}
这是一个示例 - 一个采用客户 ID 的 REST 删除操作。该参数 {id} 在声明uri-如 /customers/12345 。然后可以使用 ${header.id} 以下方法检索它:
Java DSL
rest("/api/apartments")
.get("/search?country={country}")
.to("bean:searchBean?method=byCountry(${header.country})");
XML DSL
<rest path="/api/apartments">
<get uri="/search?country={country}">
<to uri="bean:searchBean?method=byCountry(${header.country})"/>
</get>
</rest>
设置 JSON 到 POJO 转换
最后,我们需要弄清楚我们想要对我们的请求和响应消息做什么。如果您正在接收或发送 JSON,那么 Camel 如何提供帮助?
您可以手动编写自己的 JSON 字符串,但它非常麻烦,而且编写一大堆字符串连接也没什么乐趣!
答案是对您的请求和响应类型使用 POJO。是的,Java 对象。当您将 POJO 用于输入和输出消息时,Camel 可以为您的 REST 服务使用者轻松地将这些消息与 JSON 进行相互转换。如果 Jackson 在类路径上,Camel 能够做到这一点。
这是一个示例供您查看。首先,这是我编写的一个名为 ResponseType 的类,它对来自我的 RESTful API 的响应进行建模。它包含一个字段,message:
public class ResponseType {
private String message;
public ResponseType(String message) {
this.message = message;
}
public String getMessage() { }
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
为了让 Camel 自动将其从我的 REST 服务编组为 JSON,我确保 .outType() 设置了它,并且它引用了我的自定义 ResponseType 类。这告诉 Camel 它应该期望将类型为 ResponseType 的消息返回给消费者:
rest().path("/my-api").....
.get()
.outType(ResponseType.class)
.to("bean:helloBean"); // this sends the Body to the bean
由于我的 REST 操作的业务逻辑是在 Java bean 中实现的,我只需要确保我的业务逻辑方法返回一个类型为 ResponseType 的对象:
public class HelloBean {
public ResponseType sayHello() {
return new ResponseType("Hello, world!");
}
}
最后,我需要给 Camel 一个提示,将 JSON 绑定到 Java 对象。这是使用 bindingMode 配置完成的,我添加到 restConfiguration 块中:
restConfiguration()
.component("servlet")
.bindingMode(RestBindingMode.auto);
或者,如果您愿意,可以在 XML DSL 中:
<restConfiguration component="servlet" bindingMode="auto"/>
现在,当我使用curl测试服务时,HelloBean 将返回一个 ResponseType 对象。Camel 将使用 Jackson 为我自动将其编组为 JSON - 请注意我如何获得包含一个字段 的 JSON 对象 message,这就像我上面的示例 POJO:
$ curl http://localhost:8080/services/my-api
{"message":"Hello, world!"}
示例 - 使用 REST DSL 在 Camel 中创建RESTful 服务
现在我们知道使用 Camel 创建 RESTful 服务需要什么——一个将实现服务的组件,以及一些 REST DSL 糖来配置它。这个例子将:
- 使用servlet组件托管 RESTful 服务
- 在默认的 Spring Boot Web 端口上运行,即 8080
- 在 JSON 和 Java 对象之间自动转换,这样我们就不必自己搞砸了
要创建服务,请按照下列步骤操作:
- 创建一个新的 Camel Spring Boot 项目
- 在您的 Maven POM 中,添加 camel-servlet-starter 为依赖项。这将允许 Camel 将我们的服务部署到嵌入式 Tomcat 容器中:
<dependency> <groupId>org.apache.camel.springboot</groupId> <artifactId>camel-servlet-starter</artifactId> </dependency>
- 添加 camel-jackson-starter 为依赖项。这将允许 Camel 编组到/从 JSON:
<dependency> <groupId>org.apache.camel.springboot</groupId> <artifactId>camel-jackson-starter</artifactId> </dependency>
- 在 RouteBuilder 新项目的 中,添加一个 restConfiguration() 元素。
这将初始化将提供REST 服务的组件。在这个例子中,我们为此使用了 Servlet 组件。
在为服务定义任何操作之前,我们首先执行此操作:
public void configure() throws Exception { restConfiguration() .component("servlet") .bindingMode(RestBindingMode.auto); }
- 定义一个 REST 端点,并为您的每个操作(GET、POST 等)添加框架。
首先,使用服务的路径 (URI)定义 REST 端点rest。然后附加您的每个操作- 这些是您的 HTTP 动词。
REST 动词/操作的语法看起来就像熟悉的 Camel 路由。但是,from我们使用您要使用的HTTP 动词(例如get、post和 )开始每个操作,而不是delete。
语言语言
rest("/api/customers") .get().route().to("...") .post().route().to("...") .delete().route().to("...");
XML DSL
<rest path="/api/customers"> <get> <route> <to uri="..."/> </route> </get> <post> <route> <to uri="..."/> </route> </post> </rest>
该在什么时候使用哪个 HTTP 动词上?看到这篇文章的结尾,我写了一个厚颜无耻的小备忘单。
- 现在为您的 REST 操作构建您的骆驼路线!以下是已填写的 REST 服务示例:
Java DSL
rest("/customers") .get().route().to("bean:customerService?method=listCustomers") .post().route().to("jms:queue:CUSTOMERS");
XML DSL
<rest path="/customers"> <get> <route> <to uri="bean:customerService?method=listCustomers"/> </route> </get> <post> <route> <to uri="direct:post"/> </route> </post> </rest>
正如你所看到的,GET操作通过一个bean为customerService传递服务的请求。但是POST操作将请求传递给一个直接分量,direct:post。
- 要添加对自动将请求和响应转换为 JSON 的支持,请定义代表您的请求和响应消息的 POJO,例如:
public class CreateCustomerResponse { private String result; // Add some getters and setters here... }
现在,声明您的请求和响应类型,以便 Camel 知道如何将它们编组到 JSON 或从 JSON 编组:
rest() .post() .route() .type(Customer.class) .outType(CreateCustomerResponse.class) .to("direct:post");
并确保您已在REST 配置中设置绑定模式:
restConfiguration() .component("servlet") .bindingMode(RestBindingMode.auto);
就是这样!现在继续使用您需要的尽可能多的端点和操作来构建您的 REST API。
只是想看看完整的、有效的例子?单击下面的按钮查看完整示例:
获取示例代码 在 GitHub 上
HTTP 动词 |
何时使用 |
例子 |
GET |
获取/检索实体 |
GET /customers/:id |
POST |
创建一个新实体 |
POST /customers |
PUT |
更新现有实体 |
PUT /customers/:id/tags |
DELETE |
删除现有实体 |
DELETE /customers/:id |
Apache Camel 实战
Springboot 整合 Apache Camel 教程
一、Java配置
引入Apache Camel依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>spring-boot-camel</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>apache-camel</name>
<description>spring-ai</description>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<camel.version>4.5.0</camel.version>
</properties>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Apache Camel Spring Boot Starter -->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置Apache Camel
# application.properties 示例
camel.springboot.main-route-or-bean-name = MyRouteBuilder
camel.springboot.main-run-controller = true
camel:
springboot:
main-route-or-bean-name: MyRouteBuilder
main-run-controller: true
创建Camel路由
package com.example.camel;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;
@Component
public class MyRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("timer:tick?period=5000") // 每5秒触发一次
.log("Hello from Camel! 1") // 打印日志
.to("mock:result") // 发送到mock端点进行测试
.log("Hello from Camel! 2");
}
}

运行和测试你的应用
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringCamelDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCamelDemoApplication.class, args);
}
}
二、 Spring XML配置
引入Apache Camel依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>spring-boot-camel</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>apache-camel</name>
<description>spring-ai</description>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<camel.version>4.5.0</camel.version>
</properties>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Apache Camel Spring Boot Starter -->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-xml-starter</artifactId>
<version>${camel.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置Apache Camel
# application.properties 示例
camel.springboot.main-run-controller = true
camel:
springboot:
main-run-controller: true
创建Camel路由

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.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">
<route>
<from uri="timer:tick?period=5000"/>
<log message="Hello from Camel! 1"/>
<to uri="mock:result"/>
<log message="Hello from Camel! 2"/>
</route>
</camelContext>
</beans>

运行和测试你的应用
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource("classpath:camel-config.xml") // 指定XML配置文件路径
public class SpringCamelDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCamelDemoApplication.class, args);
}
}
三、Java配置 和 Spring XML配置 同时兼任
引入Apache Camel依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>spring-boot-camel</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>apache-camel</name>
<description>spring-ai</description>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<camel.version>4.5.0</camel.version>
</properties>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Apache Camel Spring Boot Starter -->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置Apache Camel
# application.properties 示例
camel.springboot.main-route-or-bean-name = MyRouteBuilder
camel.springboot.main-run-controller = true
camel:
springboot:
main-route-or-bean-name: MyRouteBuilder
main-run-controller: true
创建Camel路由
package com.example.camel;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;
@Component
public class MyRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("file:C://Apps//testSDR")
.to("file:C://Apps//testSDR//outbox");
}
}
创建XML路由

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.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">
<route>
<from uri="timer:tick?period=5000"/>
<log message="Hello from Camel! 1"/>
<to uri="mock:result"/>
<log message="Hello from Camel! 2"/>
</route>
</camelContext>
</beans>
运行和测试你的应用
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource("classpath:camel-config.xml") // 指定XML配置文件路径
public class SpringCamelDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCamelDemoApplication.class, args);
}
}

四、 XML DSL 配置
引入Apache Camel依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>spring-boot-camel</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>apache-camel</name>
<description>spring-ai</description>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<camel.version>4.5.0</camel.version>
</properties>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Apache Camel Spring Boot Starter -->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置Apache Camel

# turn off
camel.springboot.routes-include-pattern = false
# scan only in the com/foo/routes classpath
camel.springboot.routes-include-pattern = classpath:com/foo/routes/*.xml
camel:
springboot:
routes-include-pattern: false
routes-include-pattern: classpath:com/foo/routes/*.xml
创建XML路由


<?xml version="1.0" encoding="UTF-8"?>
<routes xmlns="http://camel.apache.org/schema/spring">
<route id="test">
<from uri="timer:tick?period=5000"/>
<log message="Hello from Camel! 1"/>
<to uri="mock:result"/>
<log message="Hello from Camel! 2"/>
</route>
</routes>
运行和测试你的应用
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringCamelDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCamelDemoApplication.class, args);
}
}

五、手动触发路由
引入Apache Camel依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>spring-boot-camel</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>apache-camel</name>
<description>spring-ai</description>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<camel.version>4.5.0</camel.version>
</properties>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Apache Camel Spring Boot Starter -->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置Apache Camel
# application.properties 示例
camel.springboot.main-route-or-bean-name = MyRouteBuilder
camel.springboot.main-run-controller = true
camel:
springboot:
main-route-or-bean-name: MyRouteBuilder
main-run-controller: true
创建Camel路由 ,手动触发
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyRouteBuilder extends RouteBuilder implements CommandLineRunner {
@Autowired
private CamelContext camelContext;
@Override
public void run(String... args) throws Exception {
// 手动触发 direct:start
try (ProducerTemplate template = camelContext.createProducerTemplate()) {
template.sendBody("direct:start", "Hello Camel!");
}
}
@Override
public void configure() throws Exception {
// 路由 A
from("direct:start")
.log("Processing in Route A")
.to("direct:pro_pre_CommonSDR_csl") // 跳转到路由 B
.log("Continuing in Route A after B");
// 路由 B
from("direct:pro_pre_CommonSDR_csl")
.log("Processing in Route B")
.to("mock:resultB");
}
}

运行和测试你的应用
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringCamelDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCamelDemoApplication.class, args);
}
}