Contents

Apache Camel简介

1.概述

在本文中,我们将介绍 Camel 并探讨其核心概念之一——消息路由

我们将从介绍这些基本概念和术语开始,然后介绍定义路由的两个主要选项——Java DSL 和 Spring DSL。

我们还将通过一个示例来演示这些——通过定义一个路径,该路径使用一个文件夹中的文件并将它们移动到另一个文件夹,同时为每个文件名添加时间戳。

2. 关于 Apache Camel

Apache Camel 是一个开源集成框架,旨在简化集成系统。

它允许最终用户使用相同的 API 集成各种系统,提供对多种协议和数据类型的支持,同时具有可扩展性并允许引入自定义协议。

3. Maven依赖

为了使用 Camel,我们需要先添加 Maven 依赖:

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-core</artifactId>
    <version>2.18.0</version>
</dependency>

可以在此处 找到最新版本的 Camel 工件。

3. 领域特定语言

路由和路由引擎是 Camel 的核心部分。路由包含不同系统之间集成的流程和逻辑。

为了更轻松、更简洁地定义路由,Camel 为 Java 或 Groovy 等编程语言提供了几种不同的领域特定语言 (DSL)。另一方面,它还提供了使用 Spring DSL 在 XML 中定义路由。

使用 Java DSL 或 Spring DSL 主要是用户偏好,因为大多数功能都可用。

Java DSL 提供了更多 Spring DSL 不支持的特性。然而,Spring DSL 有时更有益,因为无需重新编译代码即可更改 XML。

4. 术语和架构

现在让我们讨论基本的 Camel 术语和架构。

首先,我们将在这里看一下 Camel 的核心概念:

  • **Message **包含正在传输到路由的数据。每条消息都有一个唯一的标识符,它由正文、标题和附件构成
  • **Exchange **是消息的容器,它是在消费者在路由过程中收到消息时创建的。Exchange 允许系统之间进行不同类型的交互——它可以定义单向消息或请求-响应消息
  • **Endpoint **是系统可以接收或发送消息的通道。它可以引用 Web 服务 URI、队列 URI、文件、电子邮件地址等
  • **Component **充当端点工厂。简而言之,组件使用相同的方法和语法为不同的技术提供接口。Camel 已经在其 DSL 中为几乎所有可能的技术支持许多组件 ,但它也提供了编写自定义组件的能力
  • Processor是一个简单的 Java 接口,用于向路由添加自定义集成逻辑。它包含一个单一的*process *方法,用于在消费者收到的消息上执行自定义业务逻辑

在高层次上,Camel 的架构很简单。CamelContext代表 Camel 运行时系统,它连接不同的概念,例如路由、组件或端点。 在此之下,处理器处理端点之间的路由和转换,而端点则集成不同的系统。

5. 定义路线

可以使用 Java DSL 或 Spring DSL 定义路由。

我们将通过定义一个路由来说明这两种样式,该路由使用一个文件夹中的文件并将它们移动到另一个文件夹,同时为每个文件名添加时间戳。

5.1.使用 Java DSL 进行路由

要使用 Java DSL 定义路由,我们首先需要创建一个DefaultCamelContext实例。之后,我们需要扩展RouteBuilder类并实现包含路由流的*configure *方法:

private static final long DURATION_MILIS = 10000;
private static final String SOURCE_FOLDER = "src/test/source-folder";
private static final String DESTINATION_FOLDER 
  = "src/test/destination-folder";
@Test
public void moveFolderContentJavaDSLTest() throws Exception {
    CamelContext camelContext = new DefaultCamelContext();
    camelContext.addRoutes(new RouteBuilder() {
      @Override
      public void configure() throws Exception {
        from("file://" + SOURCE_FOLDER + "?delete=true").process(
          new FileProcessor()).to("file://" + DESTINATION_FOLDER);
      }
    });
    camelContext.start();
    Thread.sleep(DURATION_MILIS);
    camelContext.stop();
}

configure方法可以这样读取:从源文件夹读取文件,使用 FileProcessor 处理它们并将结果发送到目标文件夹。设置delete=true表示文件处理成功后将从源文件夹中删除。

为了启动 Camel,我们需要在CamelContext上调用start方法。调用Thread.sleep是为了让 Camel 有时间将文件从一个文件夹移动到另一个文件夹。

FileProcessor实现Processor接口并包含单个*process *方法,其中包含用于修改文件名的逻辑:

public class FileProcessor implements Processor {
    public void process(Exchange exchange) throws Exception {
        String originalFileName = (String) exchange.getIn().getHeader(
          Exchange.FILE_NAME, String.class);
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat(
          "yyyy-MM-dd HH-mm-ss");
        String changedFileName = dateFormat.format(date) + originalFileName;
        exchange.getIn().setHeader(Exchange.FILE_NAME, changedFileName);
    }
}

为了检索文件名,我们必须从交换中检索传入消息并访问其标题。与此类似,要修改文件名,我们必须更新消息头。

5.2. 使用 Spring DSL 进行路由

在使用 Spring DSL 定义路由时,我们使用 XML 文件来设置路由和处理器。这允许我们使用 Spring 无需代码即可配置路由,并最终为我们提供了完全控制反转的好处。

这已经在现有文章 中介绍过,因此我们将重点关注使用 Spring DSL 和 Java DSL,这通常是定义路由的首选方式。

在这种安排中,CamelContext 是在 Spring XML 文件中使用 Camel 的自定义 XML 语法定义的,但没有像使用 XML 的“纯”Spring DSL 那样的路由定义:

<bean id="fileRouter" class="com.blogdemo.camel.file.FileRouter" />
<bean id="fileProcessor" 
  class="com.blogdemo.camel.file.FileProcessor" />
<camelContext xmlns="http://camel.apache.org/schema/spring">
    <routeBuilder ref="fileRouter" />
</camelContext>

通过这种方式,我们告诉 Camel 使用FileRouter类,该类包含我们在 Java DSL 中的路由定义:

public class FileRouter extends RouteBuilder {
    private static final String SOURCE_FOLDER = 
      "src/test/source-folder";
    private static final String DESTINATION_FOLDER = 
      "src/test/destination-folder";
    @Override
    public void configure() throws Exception {
        from("file://" + SOURCE_FOLDER + "?delete=true").process(
          new FileProcessor()).to("file://" + DESTINATION_FOLDER);
    }
}

为了测试这一点,我们必须创建一个ClassPathXmlApplicationContext实例,它将在 Spring 中加载我们的CamelContext

@Test
public void moveFolderContentSpringDSLTest() throws InterruptedException {
    ClassPathXmlApplicationContext applicationContext = 
      new ClassPathXmlApplicationContext("camel-context.xml");
    Thread.sleep(DURATION_MILIS);
    applicationContext.close();
}

通过使用这种方法,我们获得了 Spring 提供的额外灵活性和好处,以及使用 Java DSL 实现 Java 语言的所有可能性。