1. 概述
Apache Camel 允許我們在 Java 中實現不同的企業集成模式。它提供 <em >ProducerTemplate</em> 接口,該接口使我們能夠將消息發送到 Camel 路由。藉助 Spring Boot,我們可以將來自 REST 端點的消息發送到 Apache Camel 路由以進行進一步處理。
在本教程中,我們將探索 <em >ProducerTemplate</em> 的基本原理,以及它如何作為 Spring Boot 端點和 Apache Camel 路由之間的橋樑。
2. 理解 ProducerTemplate
正如 JdbcTemplate 用於與數據庫交互一樣,ProducerTemplate 通過將消息從不同來源傳遞到 Camel 路由進行交互。 ProducerTemplate 接口提供的最常用的方法是:
- sendBody() – 此方法發送 inOnly 消息。 它返回 void,意味着發送方不期望從 Camel 路由接收響應
- requestBody() – 此方法允許我們發送 inOut 消息,這意味着當我們發送消息時,我們從 Camel 路由接收響應
這兩個方法允許我們實現 inOnly 和 inOut 消息模式。
3. Maven 依賴
要查看 <em >ProducerTemplate</em> 的實際應用,我們先創建一個 Spring Boot 應用程序,使用 Apache Camel,通過在 <em >pom.xml</em>> 中添加 <em >spring-boot-starter</a </em > 和camel-spring-boot-starter</a 依賴來實現:
<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 依賴項提供用於編寫 Java 中 Spring MVC 和 RESTful 應用程序的類,而 camel-spring-boot-starter 依賴項則提供與 Spring Boot 的無縫集成。
4. 創建路由
首先,讓我們通過在我們的 Spring Boot 應用程序中創建一個名為 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();
}
}在上述代碼中,我們使用 @Commponent 標註了該類,並定義了三個 Camel 路由。第一個路由接收一條消息,將其記錄到控制枱,並轉換原始消息。第二個路由將消息追加到文件中。如果 output 目錄不存在,Camel 將會自動創建它。
最終路由將消息轉發到 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");
// ...
}在上述代碼中,我們使用 @SpringBootTest 註解對測試類進行標註,並指定要測試的應用程序。最後,我們定義了兩個變量來存儲一條消息和文件路徑。
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;
}上述端點接受一個作為 URL 路徑中路徑參數傳入的 message。接下來,我們向 direct:start 路由發送一個 message 。由於我們調用了 requestBody() 方法在 producerTemplate 上,這遵循了一種 inOut 消息模式。然後,我們返回 Camel 路由轉換後的消息。
讓我們編寫一個測試以驗證響應:
@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);
}在上述代碼中,我們調用了 sendSimpleMessage() 方法,該方法在 producerTemplateController 實例上執行。然後我們驗證響應是否不為 <em >null</em>。最後,我們確認響應與預期響應相匹配。
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";
}在這裏,我們將來自端點的 message 追加到文件中。我們這裏使用 sendBody() 方法,這意味着我們不期望從 Camel 路由處收到響應,因為這使用了 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 路由
最後,我們編寫一個控制器方法,將消息發送到 direct:beanRoute 路由:
@GetMapping("/send/bean/{message}")
public String sendToBean(@PathVariable String message) {
String response = producerTemplate.requestBody("direct:beanRoute", message, String.class);
return response;
}上述端點接收到一個傳遞給 Camel 路由的消息。Camel 路由處理該消息並返回處理後的消息。
為了確認正確響應已返回,我們編寫一個測試用例。
@Test
void givenMessage_whenSendingToBean_thenReturnsUppercaseMessage() {
String inputMessage = TEST_MESSAGE;
String response = producerTemplateController.sendToBean(inputMessage);
assertNotNull(response);
assertEquals("Bean processed " + inputMessage.toUpperCase(), response);
}sendToBean() 方法將消息發送到一個將消息轉換為大寫的 Bean。 我們確認預期響應已返回。
6. 結論
在本文中,我們學習瞭如何在 Spring Boot 和 Apache Camel 應用程序中使用 <em >ProducerTemplate</em>。 此外,我們演示瞭如何使用實際示例,從 REST 端點將 inOnly 和 inOut 消息發送到 Camel 路由。