企業整合模式
EIP可用于將集成問題分解為較小的部分,并使用標準化圖形對其進行建模。 每個人都可以輕松理解這些模型。 此外,無需針對每個集成問題每次都重新發明輪子。
使用EIP,Apache Camel彌補了建模和實現之間的空白。 EIP模型與Apache Camel的DSL之間幾乎存在一對一的關系。 本文使用一個在線商店示例來說明EIP與Apache Camel的關系。
用例:在線商店中的訂單處理
通過實現一個小用例來介紹Apache Camel的主要概念。 閱讀本文后,開始自己的項目應該非常容易。 最簡單的入門方法是使用Maven原型[4]。 這樣,您可以在幾分鐘內重建以下示例。 當然,您也可以一次下載整個示例[5]。
圖1從EIP角度顯示了示例。 任務是處理在線商店的訂單。 訂單以csv格式到達。 首先,必須將訂單轉換為內部格式。 由于商店僅出售dvd和cd,因此必須拆分每個訂單的訂單項。 其他訂單項目將轉發給合作伙伴。

圖 1 :EIP集成問題的觀點
此示例顯示了EIP的優點:集成問題分為幾個小的持久性子問題。 這些子問題每次都很容易理解和解決。 在描述了用例之后,我們現在來看一下Apache Camel的基本概念。
基本概念
Apache Camel在Java虛擬機(JVM)上運行。 大多數組件都是用Java實現的。 但是,這不是新組件的要求。 例如,駱駝標本組件是用Scala編寫的。 Spring框架在某些部分中使用,例如,用于事務支持。 但是,在2.9版[6]中,Spring依賴項已降至最低。 Apache Camel的核心很小,僅包含常用組件(即,幾種技術和API的連接器),例如Log,File,Mock或Timer。
由于Apache Camel的模塊化結構,可以輕松添加更多組件。建議Maven用于依賴項管理,因為大多數技術都需要附加庫。 不過,當然也可以手動下載庫并將其添加到類路徑中。
Apache Camel的核心功能是其路由引擎。 它根據相關路由分配消息。 路由包含流和集成邏輯。 它是使用EIP和特定的DSL實現的。 每封郵件都包含一個正文,幾個標頭和可選附件。 消息從提供者發送到消費者。 在兩者之間,可以對消息進行處理,例如過濾或變換。 圖1顯示了消息如何在路由內更改。
提供者和使用者之間的消息由消息交換容器管理,該容器包含唯一的消息ID,異常信息,傳入和傳出消息(即請求和響應)以及使用的消息交換模式(MEP)。 “僅輸入” MEP用于單向消息(例如JMS),而“輸入” MEP執行請求-響應通信,例如基于客戶端HTTP的請求及其來自服務器端的響應。
在簡短解釋了Apache Camel的基本概念之后,以下各節將提供更多詳細信息和代碼示例。 讓我們從Apache Camel的體系結構開始。
建筑
圖2顯示了Apache Camel的體系結構。 CamelContext提供運行時系統。 在內部,處理器處理端點之間的事務,例如路由或轉換。 端點連接了多種要集成的技術。 Apache Camel提供了不同的DSL來實現集成問題。

圖 2 :Apache Camel的體系結構
駱駝語境
CamelContext是Apache Camel的運行時系統,并連接其不同的概念,例如路由,組件或端點。 以下代碼片段顯示了Java main方法,該方法啟動CamelContext并在30秒后停止它。 通常,CamelContext在加載應用程序時啟動,并在關機時停止。
public class CamelStarter {public static void main(String[] args) throws Exception {CamelContext context = new DefaultCamelContext();context.addRoutes(new IntegrationRoute());context.start();Thread.sleep(30000);context.stop();}}
運行時系統可以包含在JVM環境中的任何位置,包括Web容器(例如Tomcat),JEE應用服務器(例如IBM WebSphere AS),OSGi容器,甚至是云中。
領域特定語言
DSL通過使用更高的抽象級別來促進復雜項目的實現。 Apache Camel提供了幾種不同的DSL。 Java,Groovy和Scala使用面向對象的概念,并為大多數EIP提供了一種特定的方法。 另一方面,Spring XML DSL基于Spring框架并使用XML配置。 此外,OSGi藍圖XML可用于OSGi集成。
Java DSL具有最佳的IDE支持。 Groovy和Scala DSL與Java DSL類似,此外,它們還提供了現代JVM語言的典型功能,例如簡潔的代碼或閉包。 與這些編程語言相反,Spring XML DSL需要大量XML。 此外,它提供了非常強大的基于Spring的依賴項注入機制和漂亮的抽象來簡化配置(例如JDBC或JMS連接)。 在大多數使用情況下,選擇純粹是一個品味問題。 甚至可以組合。 許多開發人員使用Spring XML進行配置,而路由是通過Java,Groovy或Scala實現的。 路線
路線是Apache Camel的關鍵部分。 此處指定了集成的流程和邏輯。 以下示例顯示了使用Java DSL的路由:
public class IntegrationRoute extends RouteBuilder {@Overridepublic void configure() throws Exception {from(“file:target/inbox”).process(new LoggingProcessor()).bean(new TransformationBean(), “makeUpperCase”) .to(“file:target/outbox/dvd”);}}
DSL易于使用。 每個人都應該甚至不了解Apache Camel就能理解上面的示例。 該路線實現了所述用例的一部分。 訂單從外部來源放置在文件目錄中。 處理訂單,最后將其移動到目標目錄。
路由必須擴展“ RouteBuilder”類并覆蓋“ configure”方法。 路由本身以“ from”端點開始,并在一個或多個“ to”端點處結束。 在這兩者之間,將實現所有必要的過程邏輯。 一個“配置”方法中可以實現任意數量的路由。
以下代碼段顯示了通過Spring XML DSL實現的相同路由:
<beans … ><bean class=”mwea.TransformationBean” id=”transformationBean”/><bean class=”mwea.LoggingProcessor” id=”loggingProcessor”/><camelContext xmlns=”http://camel.apache.org/schema/spring”><package>mwea</package><route><from uri=”file:target/inbox”/><process ref=”loggingProcessor”/> <bean ref=”transformationBean”/><to uri=”file:target/outbox”/></route></camelContext></beans>
除了路線,Apache Camel的另一個重要概念是它的組件。 它們為幾乎所有技術提供集成點。
組件
同時,有超過100個組件可用。 除了HTTP,FTP,JMS或JDBC等廣泛的技術外,還支持更多技術,包括來自Amazon,Google,GoGrid和其他公司的云服務。 每個發行版中都添加了新組件。 通常,社區也很容易構建新的自定義組件。
Apache Camel的最驚人的功能是其均勻性。 所有組件都使用相同的語法和概念。 每次集成,甚至其自動單元測試都看起來相同。 因此,復雜度大大降低了。 考慮更改上面的示例:如果應該將訂單發送到JMS隊列而不是文件目錄,只需將“ to”端點從“ file:target / outbox”更改為“ jms:queue:orders”。 而已! (當然,必須先在應用程序中對JMS進行一次配置)
雖然組件提供了技術接口,但是可以使用處理器和Bean向路由添加自定義集成邏輯。
處理器和豆
除了使用EIP,您還必須經常添加單獨的集成邏輯。 這非常容易,并且始終使用相同的概念:處理器或Bean。 兩者都在上面的路線示例中使用。
處理器是一個簡單的Java界面,只有一種方法:“處理”。 在此方法內,您可以執行解決集成問題所需的任何事情,例如轉換傳入的消息,調用其他服務等等。
public class LoggingProcessor implements Processor {@Overridepublic void process(Exchange exchange) throws Exception {System.out .println(“Received Order: ” +exchange.getIn().getBody(String.class));}}
“ exchange”參數包含Message Exchange,其中包含傳入消息,傳出消息以及其他信息。 由于實現了Processor接口,因此您已經依賴于Camel API。 有時這可能是一個問題。 也許您已經擁有無法更改的現有集成代碼(即您無法實現Processor接口)? 在這種情況下,您可以使用Bean,也稱為POJO(普通的舊Java對象)。 您將收到傳入消息(這是方法的參數)并返回傳出消息,如以下片段所示:
public class TransformationBean {public String makeUpperCase(String body) {String transformedBody = body.toUpperCase();return transformedBody;
}}
上面的bean接收一個String,對其進行轉換,最后將其發送到下一個端點。 再次查看上面的路線。 傳入的消息是一個文件。 您可能想知道為什么這樣做? Apache Camel提供了另一個強大的功能:從頭開始包含150多個自動類型轉換器,例如FileToString,CollectionToObject []或URLtoInputStream。 順便說一句:可以輕松創建其他類型轉換器并將其添加到CamelContext [7]。
如果Bean僅包含一個方法,則甚至可以在路由中將其省略。 因此,上述調用也可以是.bean(new TransformationBean())而不是.bean(new TransformationBean(),“ makeUpperCase”)。
添加更多的企業集成模式
上面的路線在處理輸入訂單之前,先使用翻譯器EIP對其進行轉換。 除了這種轉換之外,還需要更多的工作來實現整個用例。 因此,在以下示例中使用了更多EIP:
public class IntegrationRoute extends RouteBuilder {@Overridepublic void configure() throws Exception {from(“file:target/inbox”).process(new LoggingProcessor()).bean(new TransformationBean()).unmarshal().csv().split(body().tokenize(“,”)).choice().when(body().contains(“DVD”)).to(“file:target/outbox/dvd”).when(body().contains(“CD”)).to(“activemq:CD_Orders”).otherwise().to(“mock:others”);}}
每個csv文件說明一個包含一個或多個訂單項的單個訂單。 camel-csv組件用于轉換csv消息。 之后,拆分器EIP分離消息正文的每個訂單項。 在這種情況下,將使用默認的分隔符(逗號)。 但是,復雜的正則表達式或腳本語言(例如XPath,XQuery或SQL)也可以用作拆分器。
每個訂單項目都必須發送到特定的處理單元(請記住:有DVD訂單,CD訂單和其他已發送給合作伙伴的訂單)。 基于內容的路由器EIP無需任何單獨的編碼工作即可解決此問題。 DVD訂單通過文件目錄處理,而CD訂單發送到JMS隊列。
在此示例中,ActiveMQ用作JMS實現。 要將ActiveMQ支持添加到Camel應用程序,只需為camel-activemq組件添加相關的maven依賴關系,或手動將JAR添加到類路徑中。 而已。 其他一些組件一次需要更多配置。 例如,如果要使用WebSphere MQ或其他JMS實現而不是ActiveMQ,則必須配置JMS提供程序。
除了dvds和cd以外,所有其他訂購商品都發送給合作伙伴。 不幸的是,該界面尚不可用。 相反,使用Mock組件暫時模擬此接口。
上面的示例令人印象深刻地展示了如何在一個路由中使用不同的接口(在本例中為File,JMS和Mock)。 盡管技術差異很大,但您始終會應用相同的語法和概念。
自動單元和集成測試
自動測試至關重要。 但是,它通常在集成項目中被忽略。 原因是由于幾種不同的技術而導致的過多的工作和很高的復雜性。
Apache Camel解決了這個問題:它通過JUnit擴展提供測試支持。 測試類必須擴展CamelTestSupport才能使用Camel強大的測試功能。 除了其他聲明外,還隱式支持模擬。 不需要其他模擬框架,例如EasyMock或Mockito。 您甚至可以模擬分別通過生產者或使用者模板將消息發送到路由或從路由接收消息。 使用該測試套件可以自動測試所有路線。 值得一提的是,每種技術的語法和概念都相同。
下面的代碼片段顯示了示例路線的單元測試:
public class IntegrationTest extends CamelTestSupport {@Beforepublic void setup() throws Exception {super.setUp();context.addRoutes(new IntegrationRoute());}@Testpublic void testIntegrationRoute() throws Exception {// Body of test message containing several order itemsString bodyOfMessage = “Harry Potter / dvd, Metallica / cd, Claus Ibsen –Camel in Action / book “;// Initialize the mock and set expected resultsMockEndpoint mock = context.getEndpoint(“mock:others”,MockEndpoint.class);mock.expectedMessageCount(1);mock.setResultWaitTime(1000);// Only the book order item is sent to the mock// (because it is not a cd or dvd)String bookBody = “Claus Ibsen – Camel in Action / book”.toUpperCase();mock.expectedBodiesReceived(bookBody);// ProducerTemplate sends a message (i.e. a File) to the inbox directorytemplate.sendBodyAndHeader(“file://target/inbox”, bodyOfMessage, Exchange.FILE_NAME , “order.csv”);Thread.sleep(3000);// Was the file moved to the outbox directory?File target = new File(“target/outbox/dvd/order.csv”);assertTrue(“File not moved!”, target.exists());// Was the file transformed correctly (i.e. to uppercase)?String content = context.getTypeConverter().convertTo(String.class, target);String dvdbody = “Harry Potter / dvd”.toUpperCase();assertEquals(dvdbody, content);// Was the book order (i.e. ?Camel in action“ which is not a cd or dvd) sent to the mock?mock.assertIsSatisfied();}}
setup方法創建一個CamelContext實例(并執行其他一些操作)。 之后,添加路由,以便可以對其進行測試。 測試本身會創建一個模擬并設定其期望值。 然后,生產者模板將消息發送到路由的“ from”端點。 最后,一些斷言驗證了結果。 該測試可以與其他JUnit測試相同的方式運行:直接在IDE中或在構建腳本中。 甚至敏捷的測試驅動開發(TDD)都是可能的。 首先,在實現相應的路由之前,必須編寫Camel測試。
如果您想了解有關Apache Camel的更多信息,第一個地址應該是“ Camel in Action”一書[8],其中詳細介紹了所有基礎知識和許多高級功能,包括每章的工作代碼示例。 胃口大開之后,讓我們現在討論何時使用Apache Camel…
系統集成的替代方法
圖3顯示了三種集成應用程序的選擇:
- 自己的定制解決方案 :實施一個針對您的問題的單獨解決方案,而無需將問題分成幾小部分。 這可行,并且可能是小型用例的最快替代方案。 您必須自己編寫所有代碼。
- 集成框架 :使用一個框架,該框架有助于使用幾種集成模式以標準化方式集成應用程序。 它大大減少了工作量。 每個開發人員都會很容易理解您的工作。 您不必每次都重新發明輪子。
- 企業服務總線(ESB) :使用ESB集成您的應用程序。 在幕后,ESB通常還使用集成框架。 但是還有更多功能,例如業務流程管理,注冊表或業務活動監視。 通常,您可以在圖形用戶界面中配置路由和諸如此類的東西(您必須自行決定是否可以降低復雜性和工作量)。 通常,ESB是一個復雜的產品。 與使用輕量級集成框架相比,學習曲線要??高得多。 但是,因此您將獲得一個非常強大的工具,該工具應該可以滿足大型集成項目中的所有要求。

如果您決定使用集成框架,那么在JVM環境中您仍然可以選擇三種不錯的選擇:Spring Integration [9],Mule [10]和Apache Camel。 它們都是輕量級的,易于使用和實施EIP。 因此,它們提供了一種集成應用程序的標準化方法,即使在非常復雜的集成項目中也可以使用它們。 可以在[11]中找到這三個集成框架的更詳細的比較。
我個人最喜歡的是Apache Camel,這是因為它具有出色的Java,Groovy和Scala DSL,并結合了許多受支持的技術。 Spring Integration和Mule僅提供XML配置。 如果我需要Mule的某些獨特的連接器來連接專有產品(例如SAP,Tibco Rendevous,Oracle Siebel CRM,Paypal或IBM的CICS交易網關),則僅使用Mule。 如果僅需要集成廣泛的技術(例如FTP,HTTP或JMS),則僅在現有的Spring項目中使用Spring Integration。 在所有其他情況下,我將使用Apache Camel。
盡管如此:無論您選擇這些輕量級集成框架中的哪個,都可以通過輕松的工作輕松實現復雜的集成項目,這將帶來很多樂趣。 切記:繁瑣的ESB通常具有太多的功能,因此也有太多不必要的復雜性和工作量。 使用正確的工具完成正確的工作!
Apache Camel已準備好用于企業集成項目
Apache Camel已于2011年7月慶祝其第四個生日[12],它代表著一個非常成熟且穩定的開源項目。 它支持在企業項目中使用的所有要求,例如錯誤處理,事務,可伸縮性和監視。 也提供商業支持。
最重要的收獲是其可用的DSL,幾乎每種可考慮的技術都有許多組件,并且事實是,無論必須集成哪種技術,都可以始終使用相同的語法和概念(甚至用于自動測試)。 因此,應該始終將Apache Camel視為重量級ESB的輕量級替代品。 通過下載本文的示例開始。 如果您需要任何幫助或更多信息,可以找到一個很棒的社區和一本寫得很好的書。
資料來源:
- [1]“企業集成模式:設計,構建和部署消息解決方案”,ISBN:0321200683,Gregor Hohpe,Bobby Woolf
- [2] Apache Camel http://camel.apache.org
- [3]內部DSL http://martinfowler.com/bliki/DomainSpecificLanguage.html
- [4]駱駝原型http://camel.apache.org/camel-maven-archetypes.html
- [5] github https://github.com/megachucky/camel-infoq上本文的示例代碼
- [6]減少對Spring JAR的依賴http://davsclaus.blogspot.com/2011/08/apache-camel-29-reduced-dependency-on.html
- [7]駱駝類型轉換器http://camel.apache.org/type-converter.html
- [8]“行動中的駱駝”,國際標準書號(ISBN):1935182366,克勞斯·易卜生,喬納森·安斯特伊,哈德良·扎巴爾恰
- [9] Spring Integration www.springsource.org/spring-integration
- [10] Mule ESB http://www.mulesoft.org
- [11] Apache Camel,Mule ESB和Spring Integration的比較http://www.kai-waehner.de/blog/2012/01/10/spoilt-for-choice-which-integration-framework-to-use-spring集成m子或阿帕奇駱駝
- [12]阿帕奇駱駝四歲生日http://camel.apache.org/2011/07/07/happy-birthday-camel.html
參考: Apache Camel教程– 有關Java EE / SOA /云計算博客的JCG合作伙伴 Kai Wahner的EIP,路由,組件,測試和其他概念的介紹 。
翻譯自: https://www.javacodegeeks.com/2012/05/apache-camel-tutorial-introduction-to.html