領先一步
VMware 提供培訓和認證,助您加速進步。
瞭解更多上週 Spring Integration 釋出了 1.0 GA 版本,受 SpringONE Americas 大會上 Adrian 主題演講(不,不是蒙提·派森的短劇,只是 Grails 的即時編碼示例)的啟發,我想展示如何在 Grails 應用程式這個稍有不同的環境下利用 Spring Integration 會很有趣。
請注意:本文轉載自我的個人部落格 @ www.russmiles.com
本系列文章將探討如何將 Spring Integration 新增到 Grails 的多種配置中,最終將形成一個用於 Spring Integration 的完整 Grails 外掛。這更像是一個線上日記,您將有機會看到我們如何邁出第一步,將 Spring Integration 引導到 Grails 應用程式中,透過使用 Spring Integration 的一些高階功能在不同基礎設施之間橋接訊息,最終運用這些經驗來建立一個 Grails 外掛,您可以用來快速輕鬆地將 Spring Integration 新增到您自己的 Grails 專案中。
如果您更喜歡在閱讀文章時擁有已完成的專案,則完整的 Grails 專案原始碼可在此處下載(注意:基於 Grails 1.1 Beta 1 構建)
要建立 Grails 應用程式,您只需確保 Grails 安裝在您的路徑上,然後從命令列發出以下命令
> grails create-app grails-plus-integration-demo
如果一切正常,您應該會看到以下輸出
... 首先是其他輸出,然後是 ...
在 <您的目錄>/grails-plus-integration-demo 處建立了 Grails 應用程式
Grails 已經從您鍵入 grails create-app 命令的任何位置在 grails-plus-integration-demo 目錄中建立了一個應用程式。切換到您的新 Grails 應用程式目錄,然後執行它以確保一切正常
> cd grails-plus-integration-demo > grails run-app
您應該會看到類似以下內容的輸出
... 其他輸出,然後 ...
伺服器正在執行。瀏覽到 https://:8080/grails-plus-integration-demo
開啟您選擇的瀏覽器,導航到正在執行的 grails 應用程式的地址,該地址應該是 https://:8080/grails-plus-integration-demo,您應該會看到類似以下內容

圖 1. 您的新 Grails 應用程式,已啟動並執行
好的,到目前為止沒有什麼突破性的,但現在我們已經準備好建立一些功能,最終將執行 Spring Integration 訊息傳遞管道。要從命令列關閉 Grails 應用程式,請按 Ctrl-C。
對於本文中我們非常簡單的示例應用程式,我們只需要一個名為“GreetingsMessage”的域物件。為此,請在您的新應用程式目錄中使用以下 grails 命令
> grails create-domain-class GreetingsMessage
然後您應該會看到類似以下內容
正在執行指令碼 /Applications/SpringSource/grails/grails-1.1-beta1/scripts/CreateDomainClass.groovy 環境設定為 development 為 GreetingsMessage 建立了 DomainClass 為 GreetingsMessage 建立了測試
建立了 GreetingsMessage 域類後,是時候新增幾個屬性了。為此,您需要編輯當前位於 grails-app/domain 目錄中的 GreetingsMessage.groovy 檔案。您只需要為我們的示例新增一行,即可允許我們傳送一個字串訊息作為 GreetingsMessage 物件的內容

圖 2. 用一個屬性更新您的域類
儲存您更新後的 GreetingsMessage 域類,就完成了。
使用命令列,建立一個名為“GreetingsMessageSender”的 grails 控制器
> grails create-controller GreetingsMessageSender
此命令應發出類似以下內容的輸出
正在執行指令碼 /Applications/SpringSource/grails/grails-1.1-beta1/scripts/CreateController.groovy 環境設定為 development 為 GreetingsMessageSender 建立了控制器 [mkdir] 建立了目錄: /Users/russellmiles/project/grails-plus-integration-demo/grails-app/views/greetingsMessageSender 為 GreetingsMessageSender 建立了測試
您現在已經建立了一個空控制器及其功能的單元測試。Grails 還在您的 grail-app/views 目錄中建立了一個名為 greetingsMessageSender 的空目錄,當您添加了一些控制器方法後,該目錄將包含您的檢視模板。
下一步是使用我們希望它支援的方法更新控制器。開啟並更新 grails-app/controllers/GreetingsMessageSender.groovy,使其與以下內容匹配

圖 3. (部分)完成的 GreetingsMessageSender 控制器
如果您對 Groovy 不太熟悉,那麼下面是該類的程式碼所做的工作
這個 send.gsp 檢視中有相當多的程式碼,所以我建議您在這裡下載程式碼,而不是自己全部輸入。但是,如果您感到勇敢,可以將下面顯示的程式碼複製到您的 send.gsp 檔案中
圖 4. 完成的 send.gsp 檢視
檢視中需要關注的關鍵程式碼是 g:form 和 flash.message 部分。g:form 包含一個輸入文字框,它將表單中的內容欄位填充到 HTTP 引數中,當表單提交時,這些引數將被 GreetingsMessageSenderController 上的 send 閉包拾取。
flash.message 程式碼顯示 flash 集合的內容,在本例中是 send 閉包新增的訊息。
您現在可以執行並嘗試這個簡單的介面了,儘管我們不期望它暫時能做太多事情。使用 grails run-app 命令再次執行您的應用程式,並導航到您的應用程式主頁,然後嘗試一下

圖 5. Grails 應用程式主頁上的新控制器連結
點選 GreetingsMessageController 會執行 'index' 方法,然後導致您的瀏覽器重定向到 send 閉包,然後您應該會看到您的新表單

圖 6. 您的傳送表單
您應該能夠在文字框中輸入一條訊息,點選“傳送”,然後,什麼都不會發生……暫時。
計劃是建立一個服務,它接受一個字串,然後簡單地將其轉換為大寫。這沒什麼太令人興奮的,但這裡是精彩的部分:我們將使其前端控制器不知道控制器在哪裡,也不知道它支援什麼介面。當然,我們可以簡單地將我們的服務注入到控制器中,但這會將我們的控制器繫結到介面級別的服務。我們在這裡要做的是將服務和控制器之間的契約表現為僅僅是將被傳遞的訊息型別,在本例中是包含單個字串的訊息。
注意:當我提到契約和訊息傳遞時,SOA 人員的耳朵可能會豎起來,意識到這與服務的目的非常接近,即您將契約宣告為將與服務終點交換的訊息型別。這絕對是故意的,但值得一提的是,儘管 Spring Integration 是 SOA 實踐的極佳促進者,但它遠不及擁有分散式、單片 ESB 那麼沉重,即使它共享一些相同的架構基礎(如訊息傳遞和終點)。典型的 ESB 實現往往會導致昂貴的 Web 服務呼叫以實現最微不足道的交換,並帶有各種包袱,而 Spring Integration 允許完全控制將交換從執行緒內訊息傳遞,透過多執行緒程序內輪詢,一直擴充套件到程序間/機器間交換(如果需要)(有關此內容,請參閱本系列即將釋出的文章)。
第一步是將 Spring Integration 庫新增到我們的示例應用程式中。Grails 為應用程式直接依賴的庫提供了特定於每個應用程式的位置。最簡單的方法是將 Spring Integration 分發 dist 目錄的內容複製到我們的 grails 應用程式的 lib 目錄中。

複製 Spring Integration dist 目錄的內容...

...到您的 Grails 應用程式根目錄中的 lib 目錄。
新增庫使 Spring Integration 可用於您的 Grails 應用程式。現在您已經準備好建立 Spring Integration 管道,在您建立了將為該管道提供服務的元件之後。
> grails create-service DemoBean
執行此命令應該會給您類似以下內容的輸出
正在執行指令碼 /Applications/SpringSource/grails/grails-1.1-beta1/scripts/CreateService.groovy 環境設定為 development 為 DemoBean 建立了 Service 為 DemoBean 建立了測試
現在 Grails 已經在 grails-app/services 目錄中建立了一個 DemoBeanService。它不是最有趣的服務,但它將用於說明 Spring Integration 機制。
要完成服務,請開啟 grails-app/services 目錄中的 DemoBeanService.groovy 檔案,並按如下所示完成它

圖 7. 完成的 DemoBeanService 類
該服務有一個方法,其目的是在返回之前將任何傳入字串轉換為大寫。現在您有了一個服務,當用戶將字串提交到控制器時您希望呼叫它,是時候將這兩個連線起來了。
現在,我們可以直接使用 DI,但對於此示例,我們將透過使用 Spring Integration 來處理將傳入字串傳遞給我們配置的特定服務,從而為更靈活的架構奠定基礎。
Grails 支援使用約定將現有的 Spring XML 配置新增到應用程式中,其中配置儲存在 grails-app/conf/spring 目錄中的 resources.xml 檔案中。為了節省您的輸入時間,請在此處下載該檔案,然後將其放入您的 grails-app/conf/spring 目錄中。
接下來,在您喜歡的文字編輯器中開啟 resources.xml,讓我們看看發生了什麼。
首先,請注意我們正在引入 Spring Integration 名稱空間,以便我們可以使用與 Spring Integration 基於 XML 的領域特定語言相關的元素和屬性。實際上,Spring Integration 名稱空間被設定為文件的預設名稱空間,因此我們必須使用名稱空間限定 bean 元素。
整個管道然後在此文件中表達。此管道中的主要元件以及這些元件所扮演的角色如下
注意:Grails 中的所有服務類預設都會生成該類的單例服務物件,該物件在 Spring 應用程式上下文中以類名的駝峰式命名版本進行索引。因此,當 service-activator 引用 demoBeanService bean 時,Grails 會自動將其解析為我們之前建立的 DemoBeanService 的單例例項。
就是這樣,我們有了一個完整的訊息傳遞管道,它將透過內部佇列傳遞訊息,將任何訊息提供者與消費者強力解耦。您會注意到,任何建立訊息並呼叫閘道器的消費者都無需知道訊息最終會發送到哪裡,甚至無需知道目標端點實現了什麼介面。這裡的契約是正在傳遞的訊息型別,對於這個簡單的示例,它們只是字串。
為了解決這些鬆散的末端,您需要建立一個您樂意暴露給控制器的服務介面。請注意,端點實際引用的 bean 不一定需要實現相同的介面,這裡重要的是訊息引數。
要建立介面,請在 src/java 目錄中建立一個名為 MessageService.java 的 Java 介面,位於適當的包結構中,如 com.russmiles.demo.grails.integration。完成介面,使其與以下內容匹配

圖 8. MessageService 介面的定義
現在您已經定義了閘道器介面,最後的工作是將閘道器本身連線到您的控制器。在 grails 中,您可以根據物件的名稱自動提供依賴項,因此要從控制器內部訪問閘道器,您所需要做的就是宣告一個名稱與閘道器 ID 匹配的屬性

圖 9. 將對閘道器的依賴項新增到您的控制器中
現在您已將閘道器連線到控制器,您可以修改您的傳送閉包以利用它

圖 10. 您完成的控制器
就這樣,是時候啟動您使用 Spring Integration 的 Grails 應用程式了。
一切都連線好後,剩下的就是讓您的應用程式執行起來。使用常用命令執行 Grails 應用程式
> grails run-app
現在訪問您的瀏覽器中的 GreetingsMessageSenderController,如下圖所示

圖 11. 您的表單,已準備好輸入以觸發您的 Spring Integration 管道
在表單中輸入一些文字並點擊發送

圖 12. 表單中輸入了一些資料並已準備就緒
下圖顯示了接下來會發生什麼

圖 13. 您的訊息,透過管道傳送並返回處理後,作為快閃記憶體訊息的一部分顯示
重申一下,當您點選“傳送”按鈕時,會發生以下情況。
當您點擊發送時,您的控制器將呼叫閘道器,閘道器將訊息作為 Spring Integration 訊息傳遞到適當的通道,服務啟用器將獲取該訊息,解包並呼叫 demoBean 服務。服務獲取字串內容並將其轉換為大寫,並透過為此交換設定的臨時通道返回結果。閘道器上的方法返回,解除控制器的阻塞,然後控制器使用快閃記憶體集合中的結果渲染檢視。