- Apache Camel 教程
- Apache Camel - 首頁
- Apache Camel - 簡介
- Apache Camel - 概述
- Apache Camel - 功能特性
- Apache Camel - 架構
- Apache Camel - CamelContext
- Apache Camel - 端點
- Apache Camel - 元件
- Apache Camel - 訊息佇列
- Apache Camel - 專案
- 使用 Camel 與 Spring
- Apache Camel 有用資源
- Apache Camel 快速指南
- Apache Camel - 有用資源
- Apache Camel - 討論
Apache Camel 快速指南
Apache Camel - 簡介
假設你所在城鎮的一家大型線上雜貨店,例如印度的 Bigbasket,邀請你為他們設計一個 IT 解決方案。這個穩定且可擴充套件的解決方案將幫助他們克服當前面臨的軟體維護問題。這家線上商店已經運營了十年。商店接受客戶對不同類別產品的線上訂單,並將這些訂單分配給相應的供應商。例如,假設你訂購了一些肥皂、油和牛奶;這三件商品將分別分配給三個相應的供應商。然後,這三個供應商將把他們的貨物傳送到一個共同的配送點,從那裡由配送中心完成整個訂單。
這家商店剛開始營業時,是透過逗號分隔的純文字檔案接收訂單。一段時間後,商店轉向了訊息驅動的訂單放置方式。後來,一些軟體開發者建議使用基於 XML 的訂單放置方式。最終,商店甚至採用了 Web 服務介面。現在,真正的難題出現了。訂單現在採用不同的格式。顯然,每次公司升級訂單接受格式時,都不想破壞之前部署的介面,以免造成客戶的混淆。
同時,隨著業務不斷增長,商店定期向其產品目錄中新增新的供應商。每個供應商都有自己接受訂單的協議。我們再次面臨整合問題;我們的應用程式架構必須能夠擴充套件以適應具有其獨特訂單放置機制的新供應商。
整個情況如下圖所示:
現在,讓我們看看 Apache Camel 如何幫助你為上述場景提供一個優雅、可維護、可擴充套件的解決方案架構。
在我們繼續討論解決方案之前,我們需要做一個小的假設。在本教程的所有討論中,我們都假設線上訂單採用 XML 格式。我們將在整個討論中使用的訂單檔案的典型格式如下所示:
<?xml version = "1.0" encoding = "UTF-8"?>
<OrderID Order = "001">
<order product = "soaps">
<items>
<item>
<Brand>Cinthol</Brand>
<Type>Original</Type>
<Quantity>4</Quantity>
<Price>25</Price>
</item>
<item>
<Brand>Cinthol</Brand>
<Type>Lime</Type>
<Quantity>6</Quantity>
<Price>30</Price>
</item>
</items>
</order>
<order product = "Oil">
<items>
<item>
<Brand>Saffola</Brand>
<Type>Gold</Type>
<Quantity>2</Quantity>
<Price>649</Price>
</item>
<item>
<Brand>Fortune</Brand>
<Type>Sunlite</Type>
<Quantity>1</Quantity>
<Price>525</Price>
</item>
</items>
</order>
<order product = "Milk">
<items>
<item>
<Product>Milk</Product>
<Brand>Amul</Brand>
<Type>Pure</Type>
<Quantity>2</Quantity>
<Price>60</Price>
</item>
</items>
</order>
</OrderID>
我們將使用上述 XML 模板來說明本教程中的 Camel 示例。
Apache Camel - 概述
Camel 是一個黑盒,它從某個端點接收訊息並將其傳送到另一個端點。在黑盒內,訊息可以被處理或簡單地重定向。
那麼為什麼要為此建立一個框架呢?在實際情況中,正如引言案例研究中所見,可能存在許多傳送者和許多接收者,每個傳送者和接收者都遵循其自身的協議,例如 ftp、http 和 jms。系統可能需要許多複雜的規則,例如來自發送者 A 的訊息只能傳遞給 B 和 C。在某些情況下,你可能需要將訊息轉換為接收者期望的另一種格式。這種轉換可能取決於訊息內容的某些條件。因此,你本質上可能需要在協議之間進行轉換、將元件粘合在一起、定義路由規則以及根據訊息內容提供過濾。如下圖所示:
為了滿足上述要求併為許多此類情況設計合適的軟體架構,Gregor Hohpe 和 Bobby Woolf 在 2003 年編制了企業整合模式(EIP)。Apache Camel 提供了這些模式的實現,本教程的目的是教你如何在引言中描述的類似情況下使用 Camel。
Apache Camel 是一個開源框架。它是一個面向訊息的中介軟體,提供基於規則的路由和中介引擎。你可以定義規則,例如,如果它是“牛奶”訂單,則將其重定向到牛奶供應商;如果它是“油”訂單,則將其重定向到油供應商,依此類推。使用 Camel,你將能夠實現這些規則並在熟悉的 Java 程式碼中進行路由。這意味著你可以使用你熟悉的 Java IDE 在型別安全的環境中定義這些規則。我們不需要使用 XML 配置檔案,這些檔案通常很冗長。雖然 Camel 透過 Spring 框架支援 XML 配置,但如果你更喜歡使用 XML 來配置規則,也可以這樣做。你甚至可以使用 Blueprint XML 配置檔案,如果你是 Scala 愛好者,還可以使用 Scala DSL。這也意味著你可以使用你最喜歡的 Java、Scala IDE 甚至簡單的 XML 編輯器來配置規則。
此引擎的輸入可以是逗號分隔的文字檔案、POJO(普通舊式 Java 物件)、XML 或 Camel 支援的幾種其他格式中的任何一種。類似地,引擎的輸出可以重定向到檔案、訊息佇列,甚至你的監視器螢幕,以便你檢視傳送給各個供應商的訂單。這些稱為端點,Camel 支援訊息端點 EIP 模式。Camel 端點將在後面的“端點”章節中討論。
Camel 通常與Apache ServiceMix、Apache ActiveMQ 和Apache CXF 一起使用來實現面向服務的架構。
Apache Camel - 功能特性
在瞭解了 Apache Camel 的概述之後,讓我們現在深入瞭解其功能,看看它提供了什麼。我們已經知道 Apache Camel 是一個開源 Java 框架,它本質上提供了各種 EIP 的實現。Camel 透過提供與各種傳輸和 API 的連線來簡化整合。例如,你可以輕鬆地將 JMS 路由到 JSON、JSON 路由到 JMS、HTTP 路由到 JMS、FTP 路由到 JMS,甚至 HTTP 路由到 HTTP,以及與微服務的連線。你只需要在兩端提供合適的端點即可。Camel 是可擴充套件的,因此將來可以輕鬆地向框架中新增更多端點。
要將 EIP 和傳輸連線在一起,可以使用特定領域語言 (DSL),例如 Java、Scala 和 Groovy。典型的 Java 路由規則可能如下所示:
from ("file:/order").to("jms:orderQueue");
此路由規則從 **order** 目錄載入檔案,使用檔案的內容建立一個 JMS 訊息,並將該訊息傳送到名為 **orderQueue** 的佇列。
以下是一些在開發 Camel 應用程式時會發現有用的 Camel 最重要功能:
Camel 支援可插入的資料 格式和此類訊息轉換的型別轉換器,因此將來可以新增新的格式和轉換器。目前,它支援幾種流行的格式和轉換器;僅舉幾例 - CSV、EDI、JAXB、JSON、XmlBeans、XStream、Flatpack、Zip。
Camel 支援可插入的語言 來在 DSL 中編寫謂詞。一些受支援的語言包括 JavaScript、Groovy、Python、PHP、Ruby、SQL、XPath、XQuery。
Camel 支援 POJO 模型,以便你可以在各個點插入 Javabean。
Camel 透過使用訊息傳遞簡化了此類大型分散式和非同步系統的測試。
現在,讓我們瞭解 Camel 的架構,並瞭解各種功能是如何實現的。
Apache Camel - 架構
Camel 架構由三個元件組成:整合引擎和路由器、處理器和元件。如下圖所示:
Camel 核心本身非常小,包含 13 個基本元件。其餘 80 多個元件位於核心之外。這有助於保持其部署位置的低依賴性,並促進將來的擴充套件。**元件** 模組為外部世界提供 **端點** 介面。端點由 URI 指定,例如你在上一章中看到的 **file:/order** 和 **jms:orderQueue**。
**處理器** 模組用於操作和中介端點之間的訊息。前面提到的 EIP 在此模組中實現。它目前支援 40 多種模式,如EIP 書籍 和其他有用的處理單元中所述。
使用 DSL 在**整合引擎和路由器** 模組中將**處理器** 和**端點** 連線在一起。連線這些元件時,可以使用過濾器根據使用者定義的條件過濾訊息。如前所述,你有多種選擇來編寫這些規則。你可以為此使用 Java、Scala、Groovy 甚至 XML。
現在,我們來看 Camel 中最重要的元件,它可以被認為是核心——**CamelContext**。
Apache Camel - CamelContext
**CamelContext** 提供對 Camel 中所有其他服務的訪問,如下圖所示:
讓我們來看看各種服務。預設情況下,登錄檔模組是一個 JNDI 登錄檔,它儲存應用程式使用的各種 JavaBean 的名稱。如果您將 Camel 與 Spring 一起使用,這將是 Spring ApplicationContext。如果您在 OSGI 容器中使用 Camel,這將是OSGI 登錄檔。顧名思義,型別轉換器包含各種已載入的型別轉換器,這些轉換器將您的輸入從一種格式轉換為另一種格式。您可以使用內建型別轉換器,也可以提供您自己的轉換機制。元件模組包含應用程式使用的元件。這些元件透過您指定的類路徑上的自動發現來載入。對於 OSGI 容器,每當啟用一個新捆綁包時,這些元件就會被載入。我們已經在前面的章節中討論了端點和路由。資料格式模組包含已載入的資料格式,最後語言模組表示已載入的語言。
此處的程式碼片段將讓您瞭解如何在 Camel 應用程式中建立CamelContext:
CamelContext context = new DefaultCamelContext();
try {
context.addRoutes(new RouteBuilder() {
// Configure filters and routes
}
}
);
DefaultCamelContext 類提供了CamelContext 的具體實現。在addRoutes 方法中,我們建立了RouteBuilder 的匿名例項。您可以建立多個RouteBuilder 例項來定義多個路由。同一上下文中的每個路由必須具有唯一的 ID。路由可以在執行時動態新增。ID 與先前定義的路由相同的路由將替換舊路由。
接下來描述RouteBuilder 例項內部的內容。
路由
路由器定義了將訊息從from 位置移動到to 位置的規則。您可以使用RouteBuilder 在 Java DSL 中定義路由。您可以透過擴充套件內建RouteBuilder 類來建立路由。路由從from 端點開始,並在一個或多個 to 端點結束。在這兩者之間,您實現處理邏輯。您可以在單個configure 方法中配置任意數量的路由。
這是一個建立路由的典型示例:
context.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:DistributeOrderDSL")
.to("stream:out");
}
}
我們覆蓋RouteBuilder 類的 configure 方法,並在其中實現我們的路由和過濾機制。在本例中,我們將從端點DistributeOrderDSL接收到的輸入重定向到控制檯,該控制檯由端點stream:out指定。
語言選擇
您可以使用不同的語言建立路由。以下是一些如何在三種不同語言中定義相同路由的示例:
Java DSL
from ("file:/order").to("jms:orderQueue");
Spring DSL
<route> <from uri = "file:/order"/> <to uri = "jms:orderQueue"/> </route>
Scala DSL
from "file:/order" -> "jms:orderQueue"
過濾器
您可以使用過濾器選擇部分輸入內容。要設定過濾器,您可以使用任何任意的Predicate實現。然後將過濾後的輸入傳送到您所需的目的地端點。在此示例中,我們過濾掉所有肥皂訂單,以便可以將其集體傳送給肥皂供應商。
from("direct:DistributeOrderDSL")
.split(xpath("//order[@product = 'soaps']/items"))
.to("stream:out");
在此示例中,我們使用了xpath謂詞進行過濾。如果您希望使用 Java 類進行過濾,請使用以下程式碼:
from("direct:DistributeOrderDSL")
.filter()
.method(new Order(),"filter")
.to("stream:out");
Order 是您使用您自己的過濾機制的自定義 Java 類。
您可以將多個謂詞組合在一個路由中,如下所示:
from("direct:DistributeOrderDSL")
.choice()
.when(header("order").isEqualTo("oil"))
.to("direct:oil")
.when(header("order").isEqualTo("milk"))
.to("direct:milk")
.otherwise()
.to("direct:d");
因此,現在所有“油”訂單都將傳送給油供應商,“牛奶”訂單將傳送給牛奶供應商,其餘訂單將傳送到公共池。
自定義處理器
您也可以使用自定義處理。以下示例建立了一個名為myCustomProcessor 的自定義處理器,並在路由構建器中使用它。
Processor myCustomProcessor = new Processor() {
public void process(Exchange exchange) {
// implement your custom processing
}
};
RouteBuilder builder = new RouteBuilder() {
public void configure() {
from("direct:DistributeOrderDSL")
.process(myProcessor);
}
};
您可以將自定義處理器與選擇和過濾結合使用,以更好地控制您的中介和路由:
from("direct:DistributeOrderDSL")
.filter(header("order").isEqualTo("milk"))
.process(myProcessor);
使用 XML
如果您願意,可以批次使用 XML 定義路由。以下 XML 程式碼片段顯示瞭如何透過 Spring XML 建立路由以及一些過濾:
<camelContext xmlns = "http://camel.apache.org/schema/spring">
<route>
<from uri = "direct:DistributeOrderXML"/>
<log message = "Split by Distribute Order"/>
<split>
<xpath>//order[@product = 'Oil']/items</xpath>
<to uri = "file:src/main/resources/order/"/>
<to uri = "stream:out"/>
</split>
</route>
</camelContext>
瞭解了路由的構建方式後,我們現在將瞭解建立端點的各種技術。
Apache Camel - 端點
我們已經瞭解了端點在我們整合程式碼中的外觀。到目前為止我們使用的表示式,例如file:/order, jms:orderQueue, direct:distributeOrderDSL都是端點。如您所見,它們遵循 URI 規範格式。在評估此 URI 時,CamelContext 將建立Endpoint 例項;您無需擔心在 DSL 中例項化Endpoint 實現。
以我們之前的示例為例,您可以在 Java DSL 中指定端點,如下所示:
from ("file:/order").to("jms:orderQueue");
在 Spring 中,如下所示:
<route> <from uri = "file:/order"/> <to uri = "jms:orderQueue"/> </route>
在這兩種情況下,端點都是一個常量字串。在某些情況下,您可能希望在執行時構建此字串。您可以透過使用 Java String 格式化程式方法來做到這一點。Camel 提供了另一種更簡單的方法來在執行時建立這些 URI 字串。為此,Camel 提供了fromF 和toF 方法,這些方法接受具有使用者指定引數的引數。以下語句說明了toF 方法的使用:
from("direct:distributeOrderDSL”).toF("file://%s?fileName=%s", path, name);
由於這些方法,無需使用 Java 內建的String格式化程式方法。
Camel 預設使用Simple語言來計算端點表示式。Simple語言主要用於評估表示式和謂詞,而無需過多考慮XPath 的複雜性。為了評估謂詞,您可以將另一種語言(例如xpath)與預設的Simple語言結合使用。這是透過使用加號來分隔其他語言來完成的。此處的程式碼片段顯示瞭如何將xpath字串連線到用Simple編寫的表示式。
from("direct:start")
.toD("jms:${orderQueue}+language:xpath:/order/@id");
在Spring中,您可以實現相同的功能,如下所示:
<route>
<from uri = "direct:start"/>
<toD uri = "jms:${orderQueue}+language:xpath:/order/@id"/>
</route>
您可以連線任意數量的語言,每種語言都用加號與前一種語言分隔。支援的語言列表可以在這裡找到。
Apache Camel - 元件
Camel 提供了多個預構建元件。
在本章中,我們將討論camel-core模組中的一些重要元件。
Bean
Bean元件將 bean 繫結到 Camel 訊息交換。建立端點的 URI 指定為bean:beanID,其中beanID 是在登錄檔中指定的 bean 的名稱。
JndiContext jndiContext = new JndiContext();
jndiContext.bind("MilkOrder", new MilkOrderProcessor());
CamelContext camelContext = new DefaultCamelContext(jndiContext);
camelContext.addRoutes(new RouteBuilder() {
public void configure() {
from("direct:bigBasket")
.to("bean:MilkOrder?method=placeOrder");
}
});
請注意如何使用bean:協議指定端點。您可以選擇指定要呼叫的 bean 方法;在這種情況下,在評估端點表示式時將呼叫名為placeOrder 的方法。MilkOrder 是在程式碼片段的前兩行註冊的MilkOrderProcessor JavaBean 的 JNDI 名稱。為了簡潔起見,此處省略了MilkOrderProcessor本身的定義。
Direct
您必須注意到在我們之前的示例中使用了Direct。要將訂單傳送給石油供應商,我們在端點規範中使用了direct:oil。使用Direct元件允許您同步呼叫端點。我們之前示例中的以下兩個程式碼片段說明了Direct 的用法:
.when(header("order").isEqualTo("oil"))
.to("direct:oil")
以及:
from("direct:DistributeOrderDSL")
.process(myProcessor);
File
File元件提供對計算機上檔案系統的訪問。使用此元件,您可以將來自其他元件的訊息儲存到本地磁碟。此外,它還允許其他 Camel 元件處理本地檔案。在使用 File 元件時,您可以使用file:directoryName[?options] 或file://directoryName[?options]作為 URI 格式。您之前已經看到過此元件的用法:
from ("file:/order").to("jms:orderQueue");
請注意,File元件預設情況下采用目錄名稱。因此,order 目錄的內容將作為輸入內容。要在order目錄中指定特定檔案,您將使用以下語句:
from ("file:/order?fileName = order.xml").to("jms:orderQueue");
Log
Log元件允許您將訊息記錄到底層日誌記錄機制。Camel 使用 Simple Logging Facade for Java (SLF4J) 作為對各種日誌記錄框架的抽象。您可以使用java.util.logging, logback, log4j進行日誌記錄。此程式碼片段說明了Log元件的用法:
from("direct:DistributeOrderDSL")
.to("bean:MilkOrder?method = placeOrder")
.to("log:com.example.com?level = INFO&showBody = true");
SEDA
SEDA元件允許您非同步呼叫同一CamelContext中的另一個端點。如果您想跨 CamelContext 例項呼叫,則需要使用VM元件。此處說明了 SEDA 的用法:
from("direct:DistributeOrderDSL")
// send it to the seda queue that is async
.to("seda:nextOrder")
在此路由中,我們將簡單地將訂單路由到nextOrder非同步佇列。已訂閱此佇列的客戶端將從此佇列中獲取訊息。
Timer
Timer元件用於定期傳送訊息,因此在測試 Camel 應用程式時非常有用。此處的程式碼片段每兩秒鐘向控制檯傳送一條測試訊息:
from("timer://testTimer?period = 2000")
.setBody()
.simple("This is a test message ${header.timer}")
.to("stream:out");
Apache Camel - 訊息佇列
大多數整合專案都使用訊息傳遞,因為它有助於建立鬆散耦合的應用程式架構。訊息傳遞可以是同步的或非同步的。JMS 支援點對點和釋出-訂閱模型。您可以對點對點使用Queue,對釋出-訂閱模型使用Topic。在 Java 平臺上,JMS - Java 訊息服務提供對訊息伺服器的介面。Apache activeMQ 就是這樣一個開源 JMS 提供程式。Camel 不附帶 JMS 提供程式;但是,它可以配置為使用 activeMQ。要使用此元件,您需要在專案中包含以下 jar 包:activemq、camel-spring 和 camel-jms。
以下程式碼片段顯示瞭如何為 activeMQ 配置 Camel。
<bean id = "jms" class = "org.apache.camel.component.jms.JmsComponent">
<property name = "connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name = "orderQueue" value = "tcp://:61000" />
</bean>
</property>
</bean>
在這裡,Camel 應用程式將開始偵聽名為orderQueue 的佇列。佇列本身是在本地主機上執行並偵聽埠 61000 的 activeMQ 訊息伺服器中設定的。完成此操作後,您的應用程式可以從應用程式中定義的任何端點向此佇列傳送或接收訊息。
最後,現在是時候將所有內容放在一個專案中,以便更深入地瞭解 Camel 應用程式是如何建立的了。
Apache Camel - 專案
我們將使用 Maven 來構建 Camel 專案。儘管我們更喜歡使用 IntelliJ IDE 進行開發。您可以為此專案使用您選擇的任何 IDE。
建立新專案
建立一個新的Maven專案並指定以下內容:
GroupId: Basket ArtifactId: Basket
選擇專案的預設位置,或者如果您願意,可以指定您選擇的目錄。
新增依賴項
您需要新增一些依賴項才能使用 Camel。依賴項新增到pom.xml 中。因此,開啟 pom.xml 並新增以下兩個依賴項:
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.20.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-stream</artifactId>
<version>2.20.0</version>
</dependency>
</dependencies>
注意 - 我們只需要應用程式的最低限度依賴項。當您從其庫中使用更多 Camel 元件時,您需要在此 pom.xml 檔案中新增相應的依賴項。
建立 Java DSL
接下來,您將在 Java DSL 中編寫過濾和路由程式碼。建立一個名為DistributeOrderDSL 的新 Java 類。將以下程式碼新增到其中:
public class DistributeOrderDSL {
public static void main(String[] args) throws Exception {
CamelContext context = new DefaultCamelContext();
try {
context.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:DistributeOrderDSL")
.split(xpath("//order[@product='soaps']/items")).to("stream:out");
// .to("file:src/main/resources/order/");
}
});
context.start();
ProducerTemplate orderProducerTemplate = context.createProducerTemplate();
InputStream orderInputStream = new FileInputStream(ClassLoader.getSystemClassLoader()
.getResource("order.xml").getFile());
orderProducerTemplate.sendBody("direct:DistributeOrderDSL", orderInputStream);
} finally {
context.stop();
}
}
}
在main方法中,我們首先透過例項化DefaultCamelContext類中提供的預設實現來建立CamelContext。
CamelContext context = new DefaultCamelContext();
接下來,我們透過建立一個匿名的RouteBuilder例項來新增路由:
context.addRoutes(new RouteBuilder() {
我們覆蓋configure方法以新增從直接 URIDistributeOrderDSL到系統控制檯的路由。我們透過使用 xpath 查詢來提供一些過濾。
public void configure() throws Exception {
from("direct:DistributeOrderDSL")
.split(xpath("//order[@product = 'soaps']/items")).to("stream:out");
// .to("file:src/main/resources/order/");
}
新增路由後,我們啟動上下文:
context.start();
接下來,我們新增建立直接 URI - DistributeOrderDSL 的程式碼。
ProducerTemplate orderProducerTemplate = context.createProducerTemplate();
InputStream orderInputStream = new FileInputStream(ClassLoader.getSystemClassLoader()
.getResource("order.xml").getFile());
最後,我們啟動處理:
orderProducerTemplate.sendBody("direct:DistributeOrderDSL", orderInputStream);
現在,由於您的 Java DSL 程式碼已完成,在測試應用程式之前唯一剩下的就是將order.xml檔案新增到您的專案中。您可以為此目的使用介紹章節中顯示的示例 XML。
測試結果
執行應用程式時,您將看到以下輸出:
<items>
<item>
<Brand>Cinthol</Brand>
<Type>Original</Type>
<Quantity>4</Quantity>
<Price>25</Price>
</item>
<item>
<Brand>Cinthol</Brand>
<Type>Lime</Type>
<Quantity>6</Quantity>
<Price>30</Price>
</item>
</items>
請注意,此處僅列出了肥皂的訂單。如果您希望將其儲存到本地檔案,只需註釋掉stream.out行,並在您的configure方法中取消註釋以下行。
// .to("file:src/main/resources/order/");
在接下來的章節中,我們將學習如何將Camel與Spring一起使用。
Apache Camel - 與Spring一起使用
我們現在將使用Spring重新建立上一章中的應用程式。這將使我們瞭解如何使用XML而不是DSL建立Camel路由。
建立新專案
建立一個新的Maven專案並指定以下內容:
GroupId: BasketWithSpring ArtifactId: BasketWithSpring
選擇專案的預設位置,或者如果您願意,可以指定您選擇的目錄。
新增依賴項
除了您在早期應用程式中使用的核心依賴項之外,您還需要新增一些其他依賴項才能使用Spring。這些依賴項已新增到pom.xml中。現在,開啟pom.xml並新增以下依賴項:
<dependencies>
...
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>5.15.2</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>5.15.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring</artifactId>
<version>2.15.1</version>
</dependency>
</dependencies>
為Spring建立Java DSL
現在讓我們建立一個名為DistributeOrderXML的新Java類。將以下程式碼新增到其中:
public class DistributeOrderXML {
public static void main(String[] args) throws Exception {
ApplicationContext appContext = new ClassPathXmlApplicationContext(
"SpringRouteContext.xml");
CamelContext camelContext = SpringCamelContext.springCamelContext(appContext, false);
try {
camelContext.start();
ProducerTemplate orderProducerTemplate = camelContext.createProducerTemplate();
InputStream orderInputStream = new FileInputStream(ClassLoader.getSystemClassLoader()
.getResource("order.xml").getFile());
orderProducerTemplate.sendBody("direct:DistributeOrderXML", orderInputStream);
} finally {
camelContext.stop();
}
}
}
在main方法中,我們首先建立一個ApplicationContext的例項,它是Spring應用程式中的核心介面。在其建構函式中,我們指定包含路由和過濾資訊的XML檔案的名稱。
ApplicationContext appContext = new ClassPathXmlApplicationContext( "SpringRouteContext.xml");
接下來,我們建立CamelContext,在其引數中指定上面建立的ApplicationContext。
CamelContext camelContext = SpringCamelContext.springCamelContext(appContext, false);
此時,我們的路由和過濾已設定完畢。因此,我們使用其start方法啟動CamelContext。與之前的案例一樣,我們定義用於載入order.xml檔案的Endpoint並啟動處理。現在,讓我們瞭解如何在XML中定義路由。
建立應用程式上下文
向專案新增一個新的XML檔案,並將其命名為SpringRouteContext.xml。將以下內容剪下並貼上到此檔案中。
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd ">
<camelContext xmlns = "http://camel.apache.org/schema/spring">
<route>
<from uri = "direct:DistributeOrderXML"/>
<log message = "Split by Distribute Order"/>
<split>
<xpath>//order[@product = 'Oil']/items</xpath>
<to uri = "file:src/main/resources/order/"/>
<to uri = "stream:out"/>
</split>
</route>
</camelContext>
</beans>
在這裡,我們定義xpath查詢如下,請注意我們現在選擇所有“oil”的訂單。
<xpath>//order[@product = 'Oil']/items</xpath>
輸出端點是多個。第一個端點指定order資料夾,第二個端點指定控制檯。
<to uri = "file:src/main/resources/order/"/> <to uri = "stream:out"/>
執行應用程式。
測試結果
執行應用程式時,您將在螢幕上看到以下輸出。
<items>
<item>
<Brand>Cinthol</Brand>
<Type>Original</Type>
<Quantity>4</Quantity>
<Price>25</Price>
</item>
<item>
<Brand>Cinthol</Brand>
<Type>Lime</Type>
<Quantity>6</Quantity>
<Price>30</Price>
</item>
</items>
檢查您指定的路徑中的order資料夾。您將找到一個新建立的檔案,其中包含上述XML程式碼。
結論
Camel提供了一個現成的框架,該框架實現了EIP以簡化您的整合專案。它支援使用領域特定語言以及使用XML。