这是用户在 2024-3-28 19:21 为 https://camel.apache.org/camel-core/getting-started/index.html 保存的双语快照页面,由 沉浸式翻译 提供双语支持。了解如何保存?

 开始


本文档将指导您了解 Apache Camel Core 的基础知识。在阅读完毕后,您将对系统集成有基本的了解,学习了该项目的一些最重要的概念,并能够创建和运行您的第一个项目。


企业集成模式(E.I.P.)书籍


关于设计模式的书籍记录了特定领域内的最佳实践。这些书籍的作者希望传播最佳实践的知识,并促进讨论架构设计的词汇。


一本关于设计模式的著名书籍是《企业集成模式:设计、构建和部署消息传递解决方案》,由 Gregor Hohpe 和 Bobby Wolf 撰写。这本被称为 E.I.P.的书描述了 65 种用于异步消息传递系统的设计模式。该书为每个模式都赋予了一个名称和一个图像,用于在架构图中使用。


Apache 骆驼核心项目


Apache Camel Core 是一个开源的、基于 Java 的项目,帮助用户实现 E.I.P.书中描述的许多设计模式。因此,我们建议我们的用户将 E.I.P.书作为参考之一。


支持文件


Apache Camel 的在线文档


右侧的链接可在指南中不同主题之间进行轻松导航。我们的文档试图涵盖新手和有经验的用户的主题。然而,有经验的用户可能想跳过他们熟悉的主题。


多年来,我们的社区已经撰写了关于 Apache Camel 的书籍、文章和教程。我们的社区还通过许多视频和演讲介绍了 Apache Camel。


一些来自会员开发的材料中的重要参考资料,可能对新用户提供重要帮助


  • 《Camel 实战第二版》这本书目前被视为 Camel 的圣经,其中有一章是免费的,强烈推荐阅读,以便更加熟悉 Camel。


  • Apache Camel 培训的基础,由 Michael Hoffman 提供。


我们强烈建议我们的用户浏览上述页面,以寻找适合他们需求的额外材料。


在线 JAVADOC 文档


我们的 API 文档以 Javadoc 格式在 javadoc.io 上提供。


与 Camel 最相关的 Javadoc API 位于以下组件(JAR 文件)中:


创建您的第一个项目


我们将从创建一个简单的集成开始。您需要在系统上安装 Apache Maven 和 JDK 11 或更高版本。


我们强烈建议您使用 Java 的 LTS 版本(即 11 或 17)。我们定期在我们的持续集成(CI)环境中使用 Java 的 LTS 版本测试 Camel。

 生成项目


您将使用 Camel 提供的各种 Maven 原型来创建您的第一个项目。原型是项目的模板。换句话说,Camel Core 提供了可用于创建项目的模板。


运行此命令以创建您的第一个 Camel Core 项目:

mvn archetype:generate -B -DarchetypeGroupId=org.apache.camel.archetypes -DarchetypeArtifactId=camel-archetype-java -DarchetypeVersion=3.18.4 -Dpackage=org.apache.camel.learn -DgroupId=org.apache.camel.learn -DartifactId=first-camel-integration -Dversion=1.0.0-SNAPSHOT


如果您以前从未使用过原型,那么这个命令看起来很长。我们将解释相关的参数。


  • -DarchetypeArtifactId :这是要使用的原型的 ID(即要使用的 Camel Core 模板之一 - 在这种情况下是 camel-archetype-java


  • -DarchetypeVersion :这是要使用的原型版本。这也是用于示例的 Camel 版本。在这个示例中,我们使用 3.18.4


  • -Dpackage :您正在创建的项目的包名称。在本指南中,我们将使用 org.apache.camel.learn


  • -DgroupId :您正在创建的项目的组 ID。在本指南中,我们将使用 org.apache.camel.learn


  • -DartifactId :您正在创建的项目的工件名称。


  • 您的项目的版本。


稍后我们将描述其他生成 Camel 项目的方法。


构建和运行项目


您可以运行以下命令来构建项目:

mvn clean package


要运行该项目,您可以运行以下命令:

mvn camel:run -Dcamel.main.durationMaxMessages=2


运行上述命令后,您应该看到以下信息:

...
[che.camel.learn.MainApp.main()] MainSupport                    INFO  Apache Camel (Main) 3.18.4 is starting
[che.camel.learn.MainApp.main()] BaseMainSupport                INFO  Auto-configuration summary
[che.camel.learn.MainApp.main()] BaseMainSupport                INFO      [JVM System Property]          camel.main.durationMaxMessages=2
[che.camel.learn.MainApp.main()] XPathBuilder                   INFO  Created default XPathFactory com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl@33cc7a16
[che.camel.learn.MainApp.main()] FileEndpoint                   INFO  Endpoint is configured with noop=true so forcing endpoint to be idempotent as well
[che.camel.learn.MainApp.main()] FileEndpoint                   INFO  Using default memory based idempotent repository with cache max size: 1000
[che.camel.learn.MainApp.main()] AbstractCamelContext           INFO  Apache Camel 3.18.4 (camel-1) is starting
[che.camel.learn.MainApp.main()] AbstractCamelContext           INFO  Routes startup (started:1)
[che.camel.learn.MainApp.main()] AbstractCamelContext           INFO      Started route1 (file://src/data)
[che.camel.learn.MainApp.main()] AbstractCamelContext           INFO  Apache Camel 3.18.4 (camel-1) started in 89ms (build:12ms init:68ms start:9ms JVM-uptime:1s)
[che.camel.learn.MainApp.main()] MainSupport                    INFO  Waiting until complete: Duration max 2 messages processed
[1) thread #1 - file://src/data] route1                         INFO  Other message
[1) thread #1 - file://src/data] route1                         INFO  UK message
[1) thread #1 - file://src/data] MainLifecycleStrategy          INFO  Duration max messages triggering shutdown of the JVM
[ CamelMainShutdownCamelContext] AbstractCamelContext           INFO  Apache Camel 3.18.4 (camel-1) is shutting down (timeout:45s)
[ CamelMainShutdownCamelContext] AbstractCamelContext           INFO  Routes stopped (stopped:1)
[ CamelMainShutdownCamelContext] AbstractCamelContext           INFO      Stopped route1 (file://src/data)
[ CamelMainShutdownCamelContext] AbstractCamelContext           INFO  Apache Camel 3.18.4 (camel-1) shutdown in 7ms (uptime:1s JVM-uptime:2s)
[che.camel.learn.MainApp.main()] MainSupport                    INFO  Apache Camel (Main) 3.18.4 shutdown


如果您在终端上看到这样的输出,意味着集成运行良好。


您刚刚运行的集成消耗了两个文件,并根据它们的内容将它们复制到一个目录中。您可以自己查看,只需查看项目中的 target/messages 目录即可。

find target/messages


你应该有以下文件:

target/messages
target/messages/others
target/messages/others/message2.xml
target/messages/uk
target/messages/uk/message1.xml


使用 Windows 资源管理器或 Windows 上类似于 Linux、macOS 或*BSDs 上的 find 命令。


理解项目


您创建的集成实现了一种模式(E.I.P.)称为基于内容的路由器。Camel 实现了这种模式,允许您根据消息的内容来实现路由逻辑。


更具体地说,这个集成会查看 src/data 目录中 XML 文件的内容。如果 city 元素的内容是伦敦,那么它将文件移动到 target/messages/uk 目录。否则,它将文件移动到 target/messages/others 目录。


为了创建执行此任务的集成,此代码配置了一个路由,将由地址 file:src/data?noop=true 表示的源端点连接到由地址 file:target/messages/ukfile:target/messages/others 表示的另外两个端点。


如果你对技术术语感到不知所措,不要担心。在接下来的部分中,我们将解释每个术语的含义以及为什么它们对基于 Camel 的集成很重要。

 终点


当我们谈论进程间通信,比如客户端/服务器或微服务时,我们经常使用术语"端点"来指代一个软件实体。在这个上下文中,一个端点的特点是它可以通过地址进行联系。地址本身可能传达了端点的其他特征。例如,地址 host:port 传达了基于 TCP 的通信端点的端口和网络名称。


地址和该地址可联系的软件之间的区别通常不重要。


过去,其他技术(如 CORBA)在使用术语"endpoint"时可能存在歧义。为了避免任何混淆,我们明确指出 Camel 仅按照我们上述描述的方式使用该术语。


Camel 为许多通信技术实现的端点提供开箱即用的支持。以下是一些受支持的端点技术的示例:

  •  一个 JMS 队列。

  •  一个网络服务。


  • 一个文件。文件可能听起来不像是一种可能的终点,直到你意识到在某些系统中,一个应用程序可能会将信息写入文件,然后另一个应用程序可能会读取该文件。

  •  一个 FTP 服务器。


  • 一个电子邮件地址。客户端可以向电子邮件地址发送消息,服务器可以从邮件服务器读取传入的消息。


  • 一个 POJO(普通的旧 Java 对象)。

 路线


在基于 Camel 的应用程序中,您创建路由。路由用于将源端点连接到目标端点。


集成、微服务和中间件领域的其他项目使用“源”和“汇”这两个术语来表示源和目标端点。Camel Core 项目不使用这种术语。


一条路由描述了一个 Message 从源端点经过任意类型的决策流程(如过滤器和路由器),到达目标端点(如果有的话)的逐步移动。


此时,您可能希望使用一个集成开发环境(IDE)来打开项目并查看文件。


在您创建的项目中,应该有 2 个源文件位于目录 src/main/java/org/apache/camel/learn 中:


  • MainApp.java :包含配置和启动应用程序的代码。


  • MyRouteBuilder.java :包含了路线的代码。


路线的代码应该是:

public class MyRouteBuilder extends RouteBuilder {
    public void configure() {
        from("file:src/data?noop=true")
            .choice()
                .when(xpath("/person/city = 'London'"))
                    .log("UK message")
                    .to("file:target/messages/uk")
                .otherwise()
                    .log("Other message")
                    .to("file:target/messages/others");
    }
}


我们将在本指南的后面部分详细阐述骆驼核心项目中路由的性质和作用。现在,让我们专注于我们创建的路由的两个最重要的方面。


  • 它扩展了 RouteBuilder ,这是在 Camel 中创建路由的基类。


  • 它使用 configure 方法来描述数据从源到目的地的逐步移动。

 路由配置


在这个路由配置中,我们将源端点(由地址 file:src/data?noop=true 表示)连接到另外两个端点(由地址 file:target/messages/ukfile:target/messages/others 表示)。在 Camel 中,统一资源标识符(URI)表示端点的地址。这些 URI 传达了对于路由和集成非常重要的附加信息。


  • 用于消费和/或生产数据的组件。

  •  资源标识符。


  • 组件的选项。


骆驼广泛使用 URI 来允许您引用端点。


URL 的意思是统一资源定位符,URI 的意思是统一资源标识符,URN 的意思是统一资源名称


一些 Camel 方法接受一个 URI 字符串作为参数。人们通常知道 URI 是“类似于 URL 的东西”,但并不总是理解 URI 与 URL 之间的关系,或者与其他缩写诸如 IRI 和 URN 之间的关系。


大多数人熟悉 URL(统一资源定位符),例如 http://…​ftp://…​\mailto:…​: 。URL 指定了资源的位置。


一个 URN 是不同“唯一标识符”方案的包装器。URN 的语法是 urn:<scheme-name>:<unique-identifier> 。URN 唯一标识一个资源(例如:书籍、人员或设备)。单独使用,URN 不指定资源的位置。


URI(统一资源标识符)是 URL 或 URN。

 终端地址


在 Camel 中,表示端点地址的 URI 采用以下格式:

component:resource[?options]


URI 的 scheme 部分表示用于消费或生产数据的组件。Camel 包含超过 300 个组件,允许您的应用程序与许多系统、协议和应用程序进行通信。


这些是 Camel 的有效 URI 示例: jms:queue:orderkafka:myTopic?groupId=KafkaConsumerFullITdirect:result 。通过查看这些 URI,我们可以确定它们使用了 jmskafkadirect 组件。


每个组件都有自己特定的功能、约束和要求,在使用它们时我们必须遵守。Camel 通过 resourceoptions 将它们暴露出来。这意味着根据我们正在使用的组件而有所不同。例如,在文件组件中,资源是一个目录;在 Kafka 组件中,资源是主题;等等。


路由配置和 EIPS


您创建的集成实现了一种模式(E.I.P.)称为基于内容的路由器。


骆驼通常通过 Java 领域特定语言(Java DSL)公开这些模式。您可以在路由中使用 Java DSL 中的方法来实现这些模式。例如,您创建的集成包含以下代码片段:

// ...
.choice()
    .when(xpath("/person/city = 'London'"))
        .log("UK message")
        .to("file:target/messages/uk")
    .otherwise()
        .log("Other message")
        .to("file:target/messages/others");
// ...


上面的代码通过评估一个谓词( when() ),该谓词测试消息体是否与 xpath 表达式( xpath("/person/city = 'London'") )匹配,来实现基于内容的路由器。如果 true ,则消息的目标端点应为 file:target/messages/uk 。否则,目标端点应为 file:target/messages/others


Camel 支持 Gregor Hohpe 和 Bobby Woolf 的优秀书籍中的大多数企业集成模式。


添加路由并运行应用程序


在执行路由之前,需要对其进行配置并添加到 CamelContext 中。


MainApp.java 文件包含执行以下步骤的代码:

public class MainApp {
    public static void main(String... args) throws Exception {
        Main main = new Main();
        main.configure().addRoutesBuilder(new MyRouteBuilder());
        main.run(args);
    }
}


我们首先创建一个主组件,配置它包含路由( main.configure().addRoutesBuilder(new MyRouteBuilder()); )。然后我们通过运行 run 方法来启动主应用程序,该方法将创建 CamelContext 并在前台执行集成,直到我们终止它(即使用 Ctrl + C )。


在这个例子中,您不直接与 CamelContext 进行交互,但它是 Camel 的一个基本部分。我们将在下一节中讨论它。


CAMEL 的基本概念和术语


在本节中,我们解释了额外的 Camel 概念和特性。

 骆驼上下文


CamelContext 是运行时系统,它将我们到目前为止介绍的所有基本概念(路由、端点、组件等)联系在一起。


此上下文对象表示 Camel 运行时系统。通常,在一个应用程序中只有一个 CamelContext 实例。


您在创建的示例应用程序中没有操作 CamelContext,因为 Main 组件为您管理了它。随着您的集成变得更加复杂,您最终将需要对其进行操作。典型的应用程序执行以下步骤:


  1. 创建上下文对象。


  2. 添加端点和可能的组件,我们将在"组件"部分讨论。


  3. 将路由添加到上下文对象以连接端点。


  4. 在上下文对象上调用 start() 操作。此操作启动 Camel 内部线程,用于处理端点中的消息发送、接收和处理。


  5. 最终在上下文对象上调用 stop() 操作。通过这样做,优雅地停止所有的端点和 Camel 内部线程。


CamelContext.start() 操作不会无限期地阻塞。 相反,它会在每个 ComponentEndpoint 内启动线程,然后 start() 返回。相反, CamelContext.stop() 等待每个 EndpointComponent 内的所有线程终止,然后 stop() 返回。


如果您在应用程序中忽略调用 CamelContext.start() ,Camel 将不会处理消息,因为内部线程将不会被创建。


如果您在终止应用程序之前忽略调用 CamelContext.stop() ,它可能会以不一致的状态终止。如果您在 JUnit 测试中忽略调用 CamelContext.stop() ,它可能会失败,因为消息没有完全处理的机会。


我们的文档包含了有关 CamelContext 的深入概述,如果您想了解更多信息。

 组件


组件是 Apache Camel 的另一个基本构建块,用于将路由连接到各种外部系统和服务。Camel 提供了大量内置组件,可以连接到各种技术和协议,如 HTTP、JMS、文件等。如果内置组件不能满足您的需求,您还可以创建自定义组件。


通常,基于 Camel 的应用程序不需要直接与组件进行交互。然而,在某些情况下,操作组件可能有助于应用程序的性能、操作或可扩展性。如果您想了解更多信息,包括编写自己所需的重要细节,我们的文档中包含了对组件的深入概述。

 信息和交流


Message 接口提供了对单个消息的抽象,例如请求、回复或异常消息。


Message 接口的公共 API 提供了获取器和设置器方法。您可以使用它们来访问消息的消息 ID、正文和各个头字段。


Exchange 接口提供了消息交换的抽象。消息交换是一个请求消息及其对应的回复或异常消息。在 Camel 中,请求、回复和异常消息分别称为 in、out 和 fault 消息。


如果您想了解更多关于 Exchange 和消息的详细信息,请参阅我们的文档。

 处理器


处理器用于实现消息交换的消费者或实现消息转换器等其他用例。


在编写路由时,您可以使用处理器在交换机上执行更复杂的逻辑。例如:

public void process(Exchange exchange) {
    final String body = exchange.getMessage().getBody(String.class);
    System.out.println(“Updated body: “ + body.replace(“city”, “county”));

    // ... more code here
}

public void configure() {
    from(“file:src/data?noop=true”)
        .process(this::process);
}


处理器的代码必须符合 Processor 接口。该接口代表处理消息的类。我们在下面展示该接口的签名:

 处理器
package org.apache.camel;

public interface Processor {
    void process(Exchange exchange) throws Exception;
}


process() 方法的参数是一个 Exchange 而不是一个 Message 。这提供了灵活性。例如,为了获取输入消息并处理它,该方法的实现最初可能调用 exchange.getIn() 方法。如果在处理过程中发生错误,则该方法可以调用 exchange.setException() 方法。


一个应用级开发者可能还想使用一个执行一些业务逻辑的类来实现 Processor 接口。


我们的文档包含了对处理器的深入概述。

 内置处理器


Camel 库中的许多类以一种方式实现了 Processor 接口,以支持 E.I.P.书中的设计模式。例如:


  • ChoiceProcessor 实现了消息路由模式,即使用级联的 if-then-else 语句将消息从输入队列路由到多个输出队列之一。


  • FilterProcessor 类会丢弃不满足指定谓词(即条件)的消息。


路由、路由构建器和 Java DSL


骆驼为应用程序开发人员提供了三种指定路由的方式:

  •  使用 XML。

  •  使用 YAML。


  • 使用 Java 领域特定语言(DSL)。


Java DSL 简介


对于许多人来说,“领域特定语言”一词意味着一个编译器或解释器,可以处理包含特定领域关键字和语法的输入文件。这不是 Camel 采取的方法。我们的文档一贯使用“Java DSL”一词,而不是“DSL”,但这并不能完全避免潜在的混淆。Camel 的“Java DSL”是一个类库,您可以以几乎与 DSL 相似的方式使用它,只是它带有一些 Java 语法的负担。


我们的文档包含 Java DSL 的深入概述。


继续学习骆驼相关知识


现在你已经学习了 Camel 的基础知识,你可以参考《使用 Camel 核心》的指南列表,这些指南可以帮助你增加对 Camel 的理解。


您还可以参考参考文档,以获取有关 Camel 的所有组件、EIP、DSL 等文档链接的访问权限。