Spring Integration入門
作者 Joshua Long 譯者 王麗娟 發(fā)布于 2009年11月10日 上午1時0分
社區(qū)
Architecture,
SOA,
Java
主題
ESB,
EAI
標(biāo)簽
eip
為什么使用Spring Integration
Spring Integration是Spring框架創(chuàng)建的又一個API,面向企業(yè)應(yīng)用集成(EAI)。說到集成,并不缺“解決辦法”:硬編碼的Java客戶端、其它ESB產(chǎn)品,還有消息隊列等更加傳統(tǒng)的應(yīng)用集成技術(shù)。Spring Integration對以上各種解決方法都有所改進,改進的方式有時還頗具戲劇效果。Spring Integration非常輕量、易于測試;幾乎沒有入門門檻,概念上比任何“自己編寫”的解決方法都要簡單。長遠(yuǎn)來看,它更為靈活、更具有適應(yīng)性。一旦 使用,你就會戀上它。Spring Integration可以和EJB、RMI、JMS這些標(biāo)準(zhǔn)技術(shù)協(xié)同使用,能讓你在一處對復(fù)雜的解決方法進行建模,從而對標(biāo)準(zhǔn)技術(shù)有所增強。這在很大程 度上簡化了這些技術(shù)的使用。由于Spring Integration非常輕量(與應(yīng)用一起部署Spring Integration服務(wù)器,不用將應(yīng)用部署到Spring Integration中去),而且很注重開發(fā)生命周期(方便配置的XML schema、友好的POJO形式API、與Spring框架和JEE的強大集成),所以你會發(fā)現(xiàn)跟其它很多的ESB產(chǎn)品相比,Spring Integration要更加適用。
相關(guān)廠商內(nèi)容
淘寶啟動免費Hosting服務(wù)(附Hosting部署幫助文檔)
淘寶開放平臺開發(fā)者聚會——廣州、深圳站開始報名
Taobao Open Platform“兵器譜”:TOP架構(gòu)組件體系介紹
案例:電子商務(wù)時代的開放API格局
12月15日索尼愛立信開發(fā)者嘉年華2009報名(團購優(yōu)惠)
Spring Integration本身就很強大,毋庸置疑,它從Spring框架中得到了強大的支持。比如說,配置格式無非還是Spring schema,這些配置格式反過來又為你抽象出了bean示例。Spring Integration的使用沒什么神奇之處,你可以自信地編寫main(String [] args)方法來完成XML配置所做的一切。Spring Integration中很多對RPC和消息的可用支持都以Spring框架的支持為基礎(chǔ)。Spring Integration配置文件中的所有內(nèi)容仍是標(biāo)準(zhǔn)的Spring 應(yīng)用上下文,和通常的Spring bean一樣,它也受益于依賴注入和運行時可用的方面(Aspect)。使用Spring Integration,應(yīng)用上下文就是總線了。比如這能使依賴于應(yīng)用上下文事件的解決方案成為可能。這是沒有獨立“運行時”的另一個原因,因為只要上下 文可用,總線就存在。
背景
企業(yè)應(yīng)用集成(EAI)是集成應(yīng)用之間數(shù)據(jù)和服務(wù)的一種應(yīng)用技術(shù)。它解決無限的問題,解決方案也幾乎沒有窮盡。工程師們已經(jīng)為這些解決方案的創(chuàng)建努力了數(shù)十年。就在最近,我們才確定了原則的最佳實踐,并對這些方案進行了分類。
現(xiàn)代EAI的模式通常要歸功于Gregor Hohpe等人編著的《企業(yè)集成模式》[1],該書對集成解決方案共有的很多集成模式進行了分類和闡述。Hohpe等人列出了四種集成風(fēng)格:
文件傳輸:兩個系統(tǒng)生成文件,文件的有效負(fù)載就是由另一個系統(tǒng)處理的消息。該類風(fēng)格的例子之一是針對文件輪詢目錄或FTP目錄,并處理該文件。 共享數(shù)據(jù)庫:兩個系統(tǒng)查詢同一個數(shù)據(jù)庫以獲取要傳遞的數(shù)據(jù)。一個例子是你部署了兩個EAR應(yīng)用,它們的實體類(JPA、Hibernate等)共用同一個表。 遠(yuǎn)程過程調(diào)用:兩個系統(tǒng)都暴露另一個能調(diào)用的服務(wù)。該類例子有EJB服務(wù),或SOAP和REST服務(wù)。 消息:兩個系統(tǒng)連接到一個公用的消息系統(tǒng),互相交換數(shù)據(jù),并利用消息調(diào)用行為。該風(fēng)格的例子就是眾所周知的中心輻射式的(hub-and-spoke)JMS架構(gòu)。
這些風(fēng)格迥然不同,因為沒有一種解決辦法能在任何情況下都良好運轉(zhuǎn)。這導(dǎo)致整個中間件領(lǐng)域都在基于這些模式尋求可用的解決辦法,通常被稱為企業(yè)服務(wù)總線(ESB)。ESB是最終的中間人:它知道如何使用各種語言在各種協(xié)議上調(diào)解傳遞的消息。
這些架構(gòu)風(fēng)格是不同的,它們各有所長。通常,JEE標(biāo)準(zhǔn)存在著不足(坦率地說,現(xiàn)今的任何開發(fā)平臺都是一樣),與其它系統(tǒng)集成時這些標(biāo)準(zhǔn)并不能提供解決方案??紤]到很多項目都是維護項目,新平臺中又有多少技術(shù)會使用舊服務(wù)或功能呢?少之又少,這太令人驚訝了。
JEE以及后來的Spring在簡化企業(yè)編程模型方面都有了長足的進步。JEE進行了標(biāo)準(zhǔn)化并商業(yè)化了常見企業(yè)問題——數(shù)據(jù)庫訪問、遠(yuǎn)程過程調(diào)用、事務(wù)、認(rèn)證、目錄服務(wù)等等。除了基本的RPC和消息,JEE中并沒有對EAI解決方案的直接支持。
JMS、REST和SOAP都與平臺無關(guān),但這是假設(shè)有單一的消息協(xié)議。比如說,有一個舊的主機應(yīng)用,其輸入、輸出都是存放在一些FTP端點上的批 處理文件,解決方案要求集成該應(yīng)用就是不可能的。簡單來說:現(xiàn)今的中間件能很好地處理常見問題,但在特殊情況的處理上就有所不足了。對大多數(shù)公告板或電子郵件列表,還是采取訂閱流程。通常,用戶給應(yīng)用發(fā)送電子郵件,應(yīng)用最終接收電子郵件、針對“訂閱”解析郵件、提取發(fā)送的郵件,然后在郵件列表中登記用戶后 發(fā)送響應(yīng)。第一反應(yīng)可能就是基于CRON或通過Quartz構(gòu)建定時器應(yīng)用,以輪詢電子郵件,或是為稍后使用的批處理文件去檢查FTP。這種辦法很快就會變得單調(diào)而脆弱。
之后復(fù)雜性會急劇上升。隨著時間的推移,應(yīng)用變得更為重要,與商業(yè)伙伴、其它應(yīng)用、其它平臺集成的負(fù)擔(dān)也變得更加昂貴。對必須進行維護的系統(tǒng)來說,每次集成都增加了系統(tǒng)間點對點的新通道。最終,集成各個端點的通道就會成為一個維持不了的爛攤子、復(fù)雜的架構(gòu)。
SpringSource的Spring Integration[2]簡化了編程方式,以此改進了標(biāo)準(zhǔn)的ESB。
如何鞏固、梳理架構(gòu)
企業(yè)應(yīng)用集成有很多模式,同樣有很多需要處理的協(xié)議。Spring Integration提供ESB風(fēng)格解決方案的建模能力,但使用方法及其便利性與Spring框架并無二致。ESB不僅能提供消息解決方案的建模能力,還有其它不同的技術(shù)/協(xié)議。
ESB中的服務(wù)
大多數(shù)ESB產(chǎn)品都有一些共性。其中最重要的有:
路由:能按條件邏輯或配置好的路由規(guī)則路由消息。 消息傳遞:對任何復(fù)雜的解決方案來說,將消息的有效負(fù)載從一種類型轉(zhuǎn)換為另一種類型都至關(guān)重要。在消息傳遞中,標(biāo)準(zhǔn)數(shù)據(jù)模型[3]模式要求系統(tǒng)提供通用的格式。處理消息自然也是ESB的另一個重要組成部分。 調(diào)解:適配器和服務(wù)映射。 復(fù)雜事件處理(CEP):根據(jù)相關(guān)性將總線上的事件處理為聚集的能力。 調(diào)用:這應(yīng)該是最明顯的一個。每個ESB都要能消費、提供服務(wù)。
除了上面列出的服務(wù),ESB通常還要包括記日志、審計、認(rèn)證(安全)和管理等機制。
如果你的需求更加復(fù)雜,那ESB會提供很大的價值。對比你在JEE平臺中已經(jīng)獲得的東西和ESB能帶給你的東西很有價值。下表比較了適合于ESB、可使用JEE作為替代解決方案的常見用例。
ESB
傳統(tǒng)JEE中間件
消息隊列
可通過XML配置,支持所有常見的消息模式。
比如說,如果你使用Spring JMS支持就不會很復(fù)雜。
RPC
通??梢韵M、提供和提取大部分RPC服務(wù)
同樣有無限的可能性,但沒有標(biāo)準(zhǔn)方法。
整合異構(gòu)系統(tǒng)
ESB旨在分離消費、標(biāo)準(zhǔn)化、提供不同消息過程中的不確定性。
JEE只能很好地支持一些用例。但這些解決方案往往會很快讓事情變得復(fù)雜。SOAP消息到FTP?批處理文件記錄到EJB調(diào)用?JEE對每一個都只提供了一半的解決方案。
安全
支持良好
支持良好
傳統(tǒng)的主機系統(tǒng)
對JEE等支持的互操作習(xí)慣有非常好的支持,包括批處理文件
除了CORBA,JEE對舊系統(tǒng)沒有更多的支持,除非這些系統(tǒng)的前端已經(jīng)使用了SOAP。
靈活的路由
路由決策在整個被支持的組件中盡可能延遲
JMS、EJB等技術(shù)指定可用性和路由的配置不盡相同。很難找到一個鳥瞰圖。
集成非標(biāo)準(zhǔn)需求的易難性
相對容易,特別是用Spring Integration作為所有內(nèi)容的POJO,也不用和應(yīng)用服務(wù)器集成;相反,你的解決方案在所有ESB產(chǎn)品中并不是標(biāo)準(zhǔn)的
需要深入了解JCA[4],或是類似于BEA Tuxedo[5]這樣一個系統(tǒng)。解決方案在所有JEE應(yīng)用服務(wù)器中都是標(biāo)準(zhǔn)的(盡管結(jié)果可能會有所不同)。
流行的解決方案
Spring Integration是新生事物,當(dāng)然會遭受質(zhì)疑。Mule[6]是一個非常受歡迎的的ESB產(chǎn)品,值得密切關(guān)注。Mule似乎有很大的影響力,在解決 方案的靈活性上也令人印象深刻。通過MuleForge[7]實現(xiàn)的開源擴展使其成為幾乎所有問題令人信服的選擇。它是一個標(biāo)準(zhǔn)的服務(wù)器:能部署并運行解 決方案。Maven插件有助于開發(fā)的生命周期。
ServiceMix[8]也比較受歡迎。ServiceMix原本基于Java業(yè)務(wù)集成規(guī)范(JBI;JSR 208[9])。JBI是構(gòu)建ESB產(chǎn)品的JCP規(guī)范。由于出身JBI,ServiceMix不如Mule那般靈活,但它正在進行改進。容器正轉(zhuǎn)向 OSGi基礎(chǔ)設(shè)施。
這里沒有列出其它所有有價值的ESB產(chǎn)品,要是有機會你還是要對它們多了解一下。有些非常有價值,值得研究。
Spring Integration開箱即用的功能表現(xiàn)得很好,非常易于使用。開發(fā)用例非常引人注目:如果你已經(jīng)被POJO和近年來測試友好的框架寵壞了,那這個框架 也是你的拿手好戲。只要你愿意,你可以使用接口或標(biāo)準(zhǔn)框架類,你還可以完全為POJO和你的領(lǐng)域模型進行編碼,或者,你可以將兩者結(jié)合使用。本文中,我選 擇在解決方案中使用一些框架類,以讓發(fā)生的事情明確,并提供一致性。有時候,太過不可思議反而會讓人困惑,盡管對入門來說很有成效。
使用入門
企業(yè)應(yīng)用集成速成
我們實際構(gòu)建一個非常普通的應(yīng)用,以此來演示開發(fā)周期。該示例易于理解,但卻沒有斧鑿之嫌。此外,它還是一個很酷的工具。需求是:允許通過電子郵件將博客發(fā)送到一個已知地址,然后由該地址發(fā)布博客。這么做有一些好的理由。
Blogger([10]Google的博客服務(wù))已經(jīng)有這個功能。但我在我博客上運行Apache Roller([11]),所以我可以使用這個解決方案。寫博客的惰性很大程度上是沒時間進入“發(fā)布”模式的副作用。Roller的軟件強迫用戶登錄并撰寫博客文章。這么做很麻煩,尤其是你每次都不得不對付WYIWYG(所見即所得)編輯器。第二,構(gòu)建該解決辦法最好的理由是,它提供了了一種簡單的集成,能與盡可能少的運轉(zhuǎn)部分集成在一起。我們可以在本文中仔細(xì)分析該辦法。盡管這是假設(shè)的,但很有實際用途。
構(gòu)建集成非常簡單,最好的“IDE”只是一張紙和一支筆??梢栽诤芏喙ぞ咧挟媹D。將圖轉(zhuǎn)換成你喜歡的ESB配置格式或工具非常簡單。ESB使用相同的術(shù)語。了解術(shù)語要比了解任何一種工具或ESB更為重要。
讓我們回顧一些ESB 101定義,權(quán)當(dāng)補習(xí)了。消息是傳遞到端點的有效負(fù)載。端點是通道的終點。通道是兩個端點間被命名的連接。通常,消息來自于消息系統(tǒng),被分發(fā)到不了解消息系統(tǒng)的應(yīng)用中。同樣的事情或者會反過來以其它方式出現(xiàn):應(yīng)用可能會發(fā)送數(shù)據(jù),但并不理解消息系統(tǒng)。針對這些問題,就需要通道適配器了。
就是這樣!這些就是你需要了解的條目,以便討論解決方案。其它條目都是這些條目之上的變異或詳細(xì)說明,或者是關(guān)于集成模式的,而不是關(guān)于集成本身。
Spring Integration概況
Spring Integration應(yīng)用就是使用Spring schema配置的簡單Java程序。如果你傾向于用常規(guī)的Spring配置來配置一切,就可以不使用schema。Schema會使事情更為簡單,這和 用schema配置使用Spring中方面的事務(wù)功能會更加簡單大致一樣。Spring Integration為一般概念(集成命名空間)提供了方便的schema,還有適配器的具體配置,比如針對電子郵件或文件類型的配置。
Spring Integration應(yīng)用處理從通道傳遞過來的消息概念。消息的生命周期始于一個端點,通常是對適配器做出的反應(yīng)。消息在經(jīng)過處理管道的過程中,會在總線內(nèi)被轉(zhuǎn)化、路由至其它通道、分發(fā)、響應(yīng),或者被中斷并發(fā)送到一個死消息通道中去。如果你使用Spring Integration接口編程——我們將在很大程度上盡可能保持內(nèi)容一致并明確,那你要處理Message對象,Message對象如圖1所示。
Message類是個包裝器,包裝被處理消息的有效負(fù)載。對它進行操作,很容易獲得有效負(fù)載和消息頭,你可以對有效負(fù)載進行類型轉(zhuǎn)換,可以檢查、改變消息頭。Spring Integration不要求你使用Message接口。你的應(yīng)用可以暴露一些方法,這些方法的參數(shù)類型跟你消息有效負(fù)載的類型相同。比如說,來自于文件適配器(可以從文件系統(tǒng)發(fā)送消息的適配器)的消息可能會被改為java.io.File實例。
讓我們來看一個集成例子,它把電子郵件發(fā)送到一個電子郵件地址,轉(zhuǎn)換電子郵件后再將其發(fā)布到博客中。
示例的配置在src/main/resources/integrationsContext.xml中。全部源碼可以從這里下載。integrationsContext.xml文件乍看起來很平常。XML頂端的bean負(fù)責(zé)將屬性文件中的變量宏替換到該XML配置腳本中。后面導(dǎo)入了另一個Spring文件,該文件包含本集成中要使用的簡單服務(wù)。再沒什么特別的了。
接下來繼續(xù)看相繼定義的四個bean,它們還是有意思的:服務(wù)催化器newBlogPublishingServiceActivator、轉(zhuǎn)換器 emailToBlogTransformer、處理器outboundBlogPostHandler和過濾器 emailsInFilterAgainstWhitelist。這四個bean會在配置的后面部分里用到。
實質(zhì)配置的第一段是poller元素,它是文檔的默認(rèn)輪詢器。確切來說,輪詢器是一種機制,在有變化時輪詢不同端點,并在感知到某些內(nèi)容發(fā)生變化后讓適配器對其做出響應(yīng),就像一個事件。出于簡單,我們?yōu)檎麄€Spring Integration配置一個默認(rèn)的輪詢器。見圖2。
接下來的三個元素是三個通道聲明。他們毫無意義,只是命名的通道而已。沒有端點或適配器的通道毫無用處。見圖3。
下一行配置了電子郵件適配器。電子郵件適配器查找發(fā)入系統(tǒng)的電子郵件,并將其放入名叫emailsIn的通道,該通道已經(jīng)在上面定義了。電子郵件發(fā)進來時,電子郵件系統(tǒng)并不會播報事件。在出現(xiàn)異常的時候(比如Spring Integration也支持的IMAP IDLE),你通常需要一些東西來輪詢電子郵件帳戶以查找新的電子郵件。只要有新消息,它們就一次閱讀一條消息,并將該消息傳遞到處理管道的下一個組件。見圖4。
現(xiàn)在消息在emailsIn通道中傳遞,被傳遞到通道的下一個組件——轉(zhuǎn)換器bean。轉(zhuǎn)換器獲取所有給它的內(nèi)容,以某種方式改變消息(我們稍后會 詳細(xì)討論這一點),然后順便發(fā)送出去。這種情況下,會給Transformer給定一個包含MimeMessage類型有效負(fù)載的Message,轉(zhuǎn)化器 用于創(chuàng)建BlogPost類型的一個對象。BlogPost是我們系統(tǒng)特定的一個領(lǐng)域類。我們在這里把它作為DTO來用,但很顯然,它來自哪里并不重要 ——如果你愿意,根據(jù)你的領(lǐng)域去處理它也可以。Transformer元素的最佳用法是:將消息格式轉(zhuǎn)換為系統(tǒng)常見的格式。這跟標(biāo)準(zhǔn)數(shù)據(jù)模式相關(guān)。
由此產(chǎn)生的BlogPost封裝在一條新消息中,其中包含原始消息的頭信息。頭信息正是你期望的那樣:特定于請求的值,可以對其訪問以獲取更多的元數(shù)據(jù)。例如,從內(nèi)部來說,Spring Integration總線給每樣內(nèi)容分配一個ID。該ID暴露為頭信息值供你使用。該ID保證是唯一的。
然后消息被發(fā)送給過濾器emailsInFilterAgainstWhitelist,該過濾器訪問有效負(fù)載獲取發(fā)送者的值。這樣做是為了確保在發(fā)布到博客的過程中你不會收到垃圾郵件。這個例子跟整個解決方案一樣,簡單的有些不合常理。你可以想象是去查詢Spring安全或LDAP,或是比這個做 得還要好的東西。見圖5:
XML配置的最后一段內(nèi)容是service-activator元素,它獲取所有給它的內(nèi)容并進行處理。在這種情況下,我們告知Spring Integration調(diào)用ID為newBlogPublishingServiceActivator的bean的 pubishIncomignBlogEntry方法。該方法負(fù)責(zé)實際獲取有效負(fù)載,并將有效負(fù)載發(fā)送給發(fā)布博客條目的服務(wù)。
然后我們就大功告成了。內(nèi)容看起來很多,但實際上就是相關(guān)XML的四段內(nèi)容。聲明通道是為了講清楚例子。poller元素只定義了一次,這樣,上下文中需要輪詢器的所有內(nèi)容都可以利用這個缺省的輪詢器了。
可能的擴展
我們定義了三個通道、四個組件。通過這樣設(shè)計構(gòu)成解決方案的組件,我們能讓這些組件在其它集成解決方案中可以重用。集成流程不僅僅限于此示例。我們 可能會在更復(fù)雜的集成中重用轉(zhuǎn)換器、過濾器,甚至是服務(wù)催化器。唯一需要重構(gòu)的是Spring Integration XML文件。有很多可能性。一個好的ESB應(yīng)該做到:盡可能晚地重構(gòu)流程設(shè)計和配置。
這里我們很容易就能想象到可以在什么地方采用該解決方案。下面是一些可能的補充。
對于某些審計工作流,使用jBPM([12])對系統(tǒng)增加支持。假設(shè)我們想在解決方案中添加業(yè)務(wù)流程管理 (BPM),比如在消息傳入時,以某種工作隊列的分類存儲該消息,以便編輯器進行核準(zhǔn)。編輯過程可以處理得跟工作流引擎內(nèi)部要求的一樣。最終的博客內(nèi)容核 準(zhǔn)后,編輯器把定稿發(fā)送到同樣的電子郵件地址,帶著某種關(guān)鍵字或識別出能用作相關(guān)ID的關(guān)鍵字。相關(guān)ID可用來讓集成解決方案繼續(xù)進行,主要表現(xiàn)在更新的 條目。見[13]。 使用Spring Integration“組播”博客。當(dāng)然,博客已經(jīng)發(fā)布了。但還有 一個問題,用舊的哲學(xué)問題來描述再合適不過了:“如果在woods中RSS訂閱已經(jīng)更新了,而沒有人輪詢到它,那博客算真正更新了嗎?”呃,也許我只是講 了大概的意思!也可以通過Twitter傳播博客標(biāo)題,可以使用接收者列表模式([16])通知博客聚合器([14]、[15]等)。 更新過濾器例子來驗證某種真正授權(quán)的服務(wù)。也許能使用LDAP或Spring安全。 除了簡單的電子郵件之外,多樣化對發(fā)布的支持。FTP、 WebDav、文件系統(tǒng)(在源碼中,電子郵件適配器的下面注釋了一個簡單的文件目錄適配器配置)等都是可行的輸入類型。更先進的例子則可以從移動客戶端發(fā) 送SMS消息。(當(dāng)然,我不確定有多少人用他們的手機寫博客。你永遠(yuǎn)也不會知道。不過只有一種方式能找到答案。)目前還沒有對此的支持,但閱讀了 Spring Integration的源碼后會發(fā)現(xiàn),很容易構(gòu)建自己的適配器。你可以使用SMSLib[17]類似的庫。
Spring Integration的不足之處
Spring Integration是全新且強大的。你可以對其背后的SpringSource的價值及其自身的不斷發(fā)展抱有信心。但這并不意味著它是完美的——它離 完美還遠(yuǎn)著哩!應(yīng)用集成不是一個新的領(lǐng)域,考慮解決方案和架構(gòu)已經(jīng)有數(shù)十年。應(yīng)用集成的一些用法按慣例包含了重量級的適配器,比如那些與SAP集成的集成 方法或JDEdwards OneWorld。Spring Integration不能直接支持這些具體情況。
盡管Spring Integration支持大量開箱即用的功能,但它對一些典型的適配器缺少支持,比如SFTP、HTTPS或AS2。目前,一些專有的解決方案能更好地支持這些需求。有些解決方案非常昂貴,所以你可以為Spring Integration試著改造第三方庫、編寫自己的適配器。如果你有興趣,你會因為為Spring Integration編寫適配器相當(dāng)簡單而感到驚喜。你要想開始創(chuàng)建解決方案,只需要看看jSch[18]、Jakarta Commons VFS[19]或Jakarta Commons Net [20]。
最終,Spring Integration可能并不是你現(xiàn)在最佳的解決方案。如果不是,請不要擔(dān)心。你在本文中學(xué)到的東西也能應(yīng)用在其他方案中。來吧,集成!
結(jié)論
Spring Integration是一個干凈、簡練的EAI手段,也是很好的ESB產(chǎn)品替代者?,F(xiàn)在的ESB方案沉重且很難引入到一些環(huán)境中。Spring Integration則是一個功能強大、低摩擦的替代方案,它能溫和地解決一些最復(fù)雜的集成問題。
以上內(nèi)容摘自于:
http://www.infoq.com/cn/articles/Spring-Integration-Joshua-Long