1. 概述

Apache Camel 允许我们在 Java 中实现各种企业集成模式。它提供了 ProducerTemplate 接口,使我们能够向 Camel 路由发送消息。结合 Spring Boot,我们可以将消息从 REST 接口传递到 Apache Camel 路由进行后续处理。

本文将深入探讨 ProducerTemplate 的核心概念,以及它如何作为 Spring Boot 接口和 Apache Camel 路由之间的桥梁。

2. 理解 ProducerTemplate

就像 JdbcTemplate 用于数据库交互一样,ProducerTemplate 通过将消息从不同源传递到 Camel 路由来实现交互。ProducerTemplate 接口最常用的两个方法是:

  • sendBody() - 发送 inOnly 消息(单向消息),返回 void,表示发送方不期望从 Camel 路由获得响应
  • requestBody() - 发送 inOut 消息(请求-响应模式),发送消息后会从 Camel 路由获取响应

这两个方法分别实现了 inOnly 和 inOut 消息模式。

3. Maven 依赖

要实际使用 ProducerTemplate,我们需要在 Spring Boot 应用中添加 Apache Camel 支持。在 pom.xml 中添加以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>3.5.3</version>
</dependency>

<dependency>
    <groupId>org.apache.camel.springboot</groupId>
    <artifactId>camel-spring-boot-starter</artifactId>
    <version>4.12.0</version>
</dependency>
  • spring-boot-starter:提供编写 Spring MVC 和 REST 应用的基础类
  • camel-spring-boot-starter:实现与 Spring Boot 的无缝集成

4. 创建路由

首先创建一个名为 CamelRoute 的类来定义 Camel 路由:

@Component
class CamelRoute extends RouteBuilder {
    @Override
    public void configure() {
        from("direct:start").log("Received: ${body}")
          .transform(simple("Hello ${body}"));
        from("direct:fileRoute").to("file://output?fileName=output.txt&fileExist=Append");
        from("direct:beanRoute").bean(ProcessingBean.class, "process");
    }

    @Bean
    public ProcessingBean processingBean() {
        return new ProcessingBean();
    }
}

这个类定义了三个路由:

  1. 第一个路由接收消息,记录到控制台,并转换消息内容
  2. 第二个路由将消息追加到文件(如果 output 目录不存在,Camel 会自动创建)
  3. 第三个路由将消息转发给 Bean 进行处理

对应的处理 Bean 类:

class ProcessingBean {
    public String process(String input) {
        return "Bean processed " + input.toUpperCase();
    }
}

这个 Bean 将消息转换为大写并返回新内容。

5. 控制器和测试类

创建控制器类并注入 ProducerTemplate:

@RestController
public class ProducerTemplateController {
    @Autowired
    private ProducerTemplate producerTemplate;
}

现在我们可以使用 sendBody()requestBody() 方法分别发送 inOnly 或 inOut 消息

创建测试类 ProducerTemplateIntegrationTest

@CamelSpringBootTest
@SpringBootTest(classes = ProducerTemplateApplication.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
class ProducerTemplateIntegrationTest {
    @Autowired
    private ProducerTemplateController producerTemplateController;

    private static final String TEST_MESSAGE = "TestMessage";
    private static final Path OUTPUT_FILE = Paths.get("output/output.txt");

    // ...
}

5.1. 发送消息到 direct:start 路由

创建一个接口向第一个 Camel 路由发送消息:

@GetMapping("/send/simple/{message}")
public String sendSimpleMessage(@PathVariable String message) {
    String response = producerTemplate.requestBody("direct:start", message, String.class);
    return response;
}

这个接口:

  1. 接收 URL 路径中的 message 参数
  2. 使用 requestBody()direct:start 路由发送消息(inOut 模式)
  3. 返回转换后的消息

测试验证:

@Test
void givenMessage_whenSendingSimpleMessage_thenReturnsProcessedMessage() {
    String inputMessage = TEST_MESSAGE;
    String response = producerTemplateController.sendSimpleMessage(inputMessage);
    assertNotNull(response, "Response should not be null");
    assertEquals("Hello " + inputMessage, response);
}

5.2. 发送消息到 direct:fileRoute 路由

添加新的 Spring Boot 接口:

@GetMapping("/send/file/{message}")
public String sendToFile(@PathVariable String message) {
    producerTemplate.sendBody("direct:fileRoute", message + "\n");
    return "Message appended to output.txt";
}

这里:

  • 使用 sendBody() 方法(inOnly 模式)
  • 不期望从路由获得响应
  • 将消息追加到文件

测试验证文件内容:

@Test
void givenMessage_whenSendingToFile_thenFileContainsMessage() throws IOException {
    String inputMessage = TEST_MESSAGE;
    String response = producerTemplateController.sendToFile(inputMessage);

    assertEquals("Message appended to output.txt", response);
    assertTrue(Files.exists(OUTPUT_FILE));
    String fileContent = Files.readString(OUTPUT_FILE);
    assertTrue(fileContent.contains(inputMessage));
}

5.3. 发送消息到 direct:beanRoute 路由

创建控制器方法向 Bean 路由发送消息:

@GetMapping("/send/bean/{message}")
public String sendToBean(@PathVariable String message) {
    String response = producerTemplate.requestBody("direct:beanRoute", message, String.class);
    return response;
}

这个接口:

  1. 接收消息并传递给 Camel 路由
  2. 路由将消息发送给 Bean 处理
  3. 返回处理后的消息

测试验证大写转换:

@Test
void givenMessage_whenSendingToBean_thenReturnsUppercaseMessage() {
    String inputMessage = TEST_MESSAGE;
    String response = producerTemplateController.sendToBean(inputMessage);
    assertNotNull(response);
    assertEquals("Bean processed " + inputMessage.toUpperCase(), response);
}

6. 结论

本文介绍了在 Spring Boot 和 Apache Camel 应用中使用 ProducerTemplate 的方法。通过实际示例,我们展示了如何从 REST 接口向 Camel 路由发送 inOnly 和 inOut 消息。

⚠️ 需要注意的是:

  • sendBody() 适用于不需要响应的场景(如文件写入)
  • requestBody() 适用于需要获取处理结果的场景(如数据转换)

完整示例代码可在 GitHub 获取。


原始标题:How to Use Apache Camel ProducerTemplate With Spring Boot | Baeldung