在Java運行時加入Camel路由
1. 概述
Apache Camel 是一個 Java 框架,可輕鬆實現各種企業整合模式 (EIP),從而為企業整合提供解決方案。
整合模式中的常見任務之一是根據特定規則和條件確定運行時的訊息路由。 Apache Camel 透過提供一種實現動態路由器 EIP 的方法來簡化此過程。
在本教程中,我們將深入研究如何在 Apache Camel 中實現動態路由的詳細信息,並透過範例進行演練。
2.了解動態路由器
有時,我們希望在運行時根據特定的規則和條件將訊息發送到不同的路由。 Routing Slip EIP 等解決方案可以幫助解決問題,但效率較低,因為它需要反覆試驗。
在路由表 EIP 中,訊息包含要依定義的順序路由到的端點清單。這需要預先配置端點清單並使用試誤方法透過每個端點傳送訊息。
動態路由器 EIP 提供了更好的實作來在運行時添加路由,特別是在我們有多個收件者或根本沒有收件者的情況下。它提供了路由訊息的靈活性,無需預先配置嚴格的端點。
此外,它還知道每個目的地以及將訊息路由到特定目的地的規則。此外,它還有一個控制通道,潛在目的地可以透過在啟動時宣布其存在和參與規則來與其進行通訊。
此外,它將所有可能目的地的規則儲存在規則庫中。訊息到達後,它會檢查規則庫並滿足收件人的請求。
下圖顯示了動態路由器 EIP 的內部結構:
此外,一個常見的用例是動態服務發現,其中客戶端應用程式可以透過發送包含服務名稱的訊息來存取服務。
動態路由器 EIP 的核心目標是將路由決策延遲到執行時,而不是預先建立靜態規則。
3.Maven依賴
讓我們透過將camel-core
和camel-test-junit5
加入pom.xml
來引導一個簡單的Apache Camel專案:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test-junit5</artifactId>
<version>4.3.0</version>
</dependency>
Camel Core 提供動態路由器 EIP 以及其他路由功能,Camel Test JUnit5 透過CamelSupport
介面協助更輕鬆地測試訊息路由。
值得注意的是,我們也可以將 Camel 專案引導為 Spring Boot 專案。
4. 使用動態路由器在運作時加入路由
動態路由器 EIP 確保我們為整合系統指定規則,以幫助在運行時正確匹配特定路由。它檢查傳入訊息的正文並將其與路由進行匹配。
4.1.配置
首先,我們建立一個名為DynamicRouteBean
的類別並新增一個方法來定義規則和條件:
class DynamicRouterBean {
public String route(String body, @ExchangeProperties Map<String, Object> properties) {
int invoked = (int) properties.getOrDefault("invoked", 0) + 1;
properties.put("invoked", invoked);
if (invoked == 1) {
switch (body.toLowerCase()) {
case "mock":
return "mock:dynamicRouter";
case "direct":
return "mock:directDynamicRouter";
case "seda":
return "mock:sedaDynamicRouter";
case "file":
return "mock:fileDynamicRouter";
default:
break;
}
}
return null;
}
}
在上面的程式碼中,我們根據傳入的訊息正文和當前呼叫計數動態來確定適當的路由。 route()
方法檢查訊息正文是否符合任何預先定義的關鍵字規則並傳回對應的路由。
此外,我們在Map
物件上使用@ExchangeProperties
註釋。此映射用作儲存和檢索交換的當前狀態並更新呼叫計數的容器。
此外, invoked
變數表示呼叫route()
方法的次數。如果訊息符合預定義條件並且是第一次調用,則返回相應的路由。 invoked == 1
檢查有助於在第一次呼叫時執行動態路由邏輯。這簡化了這種特定情況下的程式碼並防止不必要的重新執行。
另外,為了防止動態路由器無休止地執行, route()
方法在路由到適當的端點後傳回null
。這確保了動態路由在基於訊息識別出路由後結束。
簡單地說,每次交換都會呼叫route()
方法,直到回傳null
。
最後,讓我們在 Camel 路由建構器中設定動態路由器 EIP:
class DynamicRouterRoute extends RouteBuilder {
@Override
void configure() {
from("direct:dynamicRouter")
.dynamicRouter(method(DynamicRouterBean.class, "route"));
}
}
在上面的程式碼中,我們建立了擴充 RouteBuilder 的DynamicRouterRoute
類別RouteBuilder.
接下來,我們重寫configure方法並透過呼叫dyamicRouter()
方法來新增動態路由bean,以將動態路由器呼叫連接到我們的自訂route()
。
值得注意的是,我們可以在定義規則的方法上使用@DynamicRouter
註解:
class DynamicRouterBean {
@DynamicRouter
String route(String body, @ExchangeProperties Map<String, Object> properties) {
// ...
}
}
此註解消除了在Camel路由中明確配置dynamicRouter()
方法的需要:
// ...
@Override
void configure() {
from("direct:dynamicRouter").bean(DynamicRouterBean.class, "route");
}
// ...
在上面的程式碼中,我們使用bean()
方法來指定包含路由邏輯的類別。不再需要dynamicRouter()
方法,因為route()
方法用@DynamicRouter
註解。
4.2.單元測試
讓我們寫一個單元測試來斷言某些條件是否為真。首先,讓我們確保我們的測試類別擴充CamelTestSupport
:
class DynamicRouterRouteUnitTest extends CamelTestSupport {
@Override
protected RoutesBuilder createRouteBuilder() {
return new DynamicRouterRoute();
}
}
在這裡,提供一個DynamicRouterRoute
實例,用作測試的路由建構器。
接下來,讓我們來看看名為mock
的傳入訊息正文:
@Test
void whenMockEndpointExpectedMessageCountOneAndMockAsMessageBody_thenMessageSentToDynamicRouter() throws InterruptedException {
MockEndpoint mockDynamicEndpoint = getMockEndpoint("mock:dynamicRouter");
mockDynamicEndpoint.expectedMessageCount(1);
template.send("direct:dynamicRouter", exchange -> exchange.getIn().setBody("mock"));
MockEndpoint.assertIsSatisfied(context);
}
在這裡,我們模擬動態端點並將預期的訊息路由設定為其值。接下來,我們將預期訊息計數設為 1。最後,我們使用預期的正文訊息設定傳入訊息路由,並斷言MockEndpoint
路由已滿足.
另外,讓我們模擬「 mock:directDynamicRouter
」訊息路由:
@Test
void whenMockEndpointExpectedMessageCountOneAndDirectAsMessageBody_thenMessageSentToDynamicRouter() throws InterruptedException {
MockEndpoint mockDynamicEndpoint = context.getEndpoint("mock:directDynamicRouter", MockEndpoint.class);
mockDynamicEndpoint.expectedMessageCount(1);
template.send("direct:dynamicRouter", exchange -> exchange.getIn().setBody("direct"));
MockEndpoint.assertIsSatisfied(context);
}
此測試驗證當「 direct
」作為訊息正文發送時,它會動態路由到「 mock:directDynamicRouter
」端點。此外,我們將預期訊息計數設為 1,表示端點應接收的訊息交換數。
5. 結論
在本文中,我們學習如何使用動態路由器 EIP 在 Apache Camel 中執行時新增路由。與使用試誤方法將訊息傳送到路由的路由滑動不同,動態路由器 EIP 提供了可靠的實作來根據特定規則和條件路由到端點。
與往常一樣,範例的完整原始程式碼可在 GitHub 上取得。