將 Flex 集成到 Java EE 應用程序的最佳實踐![]() |
![]() |
![]() |
級別: 中級 廖 雪峰 ( askxuefeng@gmail.com ), 軟件工程師, HP 2009 年 8 月 05 日 傳統的 Java EE 應用程序通常使用某種 MVC 框架(例如,Struts)作為前端用戶界面,隨著 Flex 的興起,基于 RIA 的客戶端能夠給用戶帶來更酷的界面,更短的響應時間,以及更接近于桌面應用程序的體驗。本文將講述如何將 Flex 集成至一個現有的 Java EE 應用程序中,以及如何應用最佳實踐高效率地并行開發 Java EE 和 Flex。<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES--> 本文的開發環境為 Windows 7 Ultimate,Eclipse 3.4,Flex Builder 3(從 參考資源 獲得下載鏈接)。Java EE 服務器使用 Resin 3.2,當然,您也可以使用 Tomcat 等其他 Java EE 服務器。
假定我們已經擁有了一個管理雇員信息的 Java EE 應用,名為 EmployeeMgmt-Server,結構如 圖 1 所示: 圖 1. Java EE 工程結構 ![]() 這是一個典型的 Java EE 應用,使用了流行的 Spring 框架。為了簡化數據庫操作,我們使用了內存數據庫 HSQLDB。對這個簡單的應用,省略了 DAO,直接在 Fa?ade 中通過 Spring 的 JdbcTemplate 操作數據庫。最后,EmployeeMgmt 應用通過 Servlet 和 JSP 頁面為用戶提供前端界面: 圖 2. EmployeeMgmt Web 界面 ![]() 該界面為傳統的 HTML 頁面,用戶每次點擊某個鏈接都需要刷新頁面。由于 Employee Management 系統更接近于傳統的桌面應用程序,因此,用 Flex 重新編寫界面會帶來更好的用戶體驗。
如何將 Flex 集成至該 Java EE 應用呢?現在,我們希望用 Flex 替換掉原有的 Servlet 和 JSP 頁面,就需要讓 Flex 和 Java EE 后端通信。Flex 支持多種遠程調用方式,包括 HTTP,Web Services 和 AMF。不過,針對 Java EE 開發的服務器端應用,可以通過集成 BlazeDS,充分利用 AMF 協議并能輕易與 Flex 前端交換數據,這種方式是 Java EE 應用程序集成 Flex 的首選。 BlazeDS 是 Adobe LifeCycle Data Services 的開源版本,遵循 LGPL v3 授權,可以免費使用。BlazeDS 為 Flex 提供了基于 AMF 二進制協議的遠程調用支持,其作用相當于 Java 的 RMI。有了 BlazeDS,通過簡單的配置,一個 Java 接口就可以作為服務暴露給 Flex,供其遠程調用。 盡管現有的 EmployeeMgmt 應用程序已經有了 Fa?ade 接口,但這個接口是暴露給 Servlet 使用的,最好能再為 Flex 定義另一個接口 FlexService,并隱藏 Java 語言的特定對象(如 清單 1 所示): 清單 1. FlexService interface
現在,Java EE 后端與 Flex 前端的接口已經定義好了,要完成 Java EE 后端的接口實現類非常容易,利用 Spring 強大的依賴注入功能,可以通過幾行簡單的代碼完成: 清單 2. FlexServiceImpl class
然后,我們將 BlazeDS 所需的 jar 包放至
清單 3. BlazeDS 依賴的 Jar
在 web.xml 中添加 HttpFlexSession 和 Servlet 映射。HttpFlexSession 是 BlazeDS 提供的一個 Listener,負責監聽 Flex 遠程調用請求,并進行一些初始化設置: 清單 4. 定義 Flex Listener
MessageBrokerServlet 是真正處理 Flex 遠程調用請求的 Servlet,我們需要將其映射到指定的 URL: 清單 5. 定義 Flex servlet
BlazeDS 所需的所有配置文件均放在 /WEB-INF/flex/ 目錄下。BlazeDS 將讀取 services-config.xml 配置文件,該配置文件又引用了 remoting-config.xml、proxy-config.xml 和 messaging-config.xml 這 3 個配置文件,所以,一共需要 4 個配置文件。 由于 BlazeDS 需要將 Java 接口 FlexService 暴露給 Flex 前端,因此,我們在配置文件 remoting-config.xml 中將 FlexService 接口聲明為一個服務: 清單 6. 定義 flexService 服務
服務名稱通過 destination 的 id 屬性指定,Flex 前端通過該服務名稱來進行遠程調用。scope 指定為 application,表示該對象是一個全局對象。 然而,按照默認的聲明,BlazeDS 會去實例化 FlexService 對象。對于一個 Java EE 應用來說,通常這些服務對象都是被容器管理的(例如,Spring 容器或 EJB 容器),更合適的方法是查找該服務對象而非直接實例化。因此,需要告訴 BlazeDS 通過 Factory 來查找指定的 FlexService 對象,修改配置如下: 清單 7. 通過 factory 定義 flexService
現在,Flex 如何才能通過 BlazeDS 調用 FlexService 接口呢?由于 FlexService 對象已經被 Spring 管理,因此,我們需要編寫一個 FlexFactory 告訴 BlazeDS 如何找到 Spring 管理的 FlexService 的實例。flexFactory 在 services-config.xml 中指定: 清單 8. 定義 flexFactory
FlexFactoryImpl 實現了 FlexFactory 接口,該接口完成兩件事情:
因此,需要一個 FactoryInstance 的實現類,我們編寫一個 SpringFactoryInstance,以便從 Spring 的容器中查找 FlexService: 清單 9. SpringFactoryInstance class
FlexFactoryImpl 負責實例化 SpringFactoryInstance 并通過 SpringFactoryInstance 的
清單 10. FlexFactoryImpl class
以下是 BlazeDS 查找 FlexService 接口的過程:
注意到 destination 的 id 并沒有寫死在代碼中,而是通過以下語句獲得的: 清單 11. 獲取 destination 的 ID
Property 的 SOURCE 屬性由 BlazeDS 讀取 XML 配置文件獲得: 清單 12. 配置 destination 的 id
如果您沒有使用 Spring 框架,也不要緊,只需修改 FactoryInstance 的 lookup() 方法。例如,對于一個 EJB 來說,lookup() 方法應該通過 JNDI 查找返回遠程接口。無論應用程序結構如何,我們的最終目標是向 BlazeDS 返回一個 FlexService 的實例對象。
首先安裝 Flex Builder 3,可以在 Adobe 的官方網站獲得 30 天免費試用版。然后,打開 Flex Builder 3,創建一個新的 Flex Project,命名為 EmployeeMgmt-Flex: 圖 3. 新建 Flex 工程 - 第一步 ![]() Flex Project 需要指定 Server 端的配置文件地址: 圖 4. 新建 Flex 工程 - 第二步 ![]()
因此,需要填入 EmployeeMgmt-Server 項目的 web 根目錄,該目錄下必須要存在
一個 Flex Project 的目錄結構如下: 圖 5. Flex 工程的目錄結構 ![]() 用 Flex Builder 做出漂亮的用戶界面非常容易。Flex Builder 提供了一個可視化的編輯器,通過簡單的拖拽,一個毫無經驗的開發人員也能夠設計出漂亮的布局。如果熟悉一點 XML 的知識,編輯 MXML 也并非難事。我們設計的 Employee Management 系統界面的最終效果如下: 圖 6. 用 Flex Builder 的可視化編輯器設計界面 ![]() 本文不打算討論如何編寫 Flex 界面,而是把重點放在如何實現遠程調用。 為了能在 Flex 中實現遠程調用,我們需要定義一個 RemoteObject 對象。可以通過 ActionScript 編碼創建該對象,也可以直接在 MXML 中定義一個 RemoteObject 對象,并列出其所有的方法: 清單 13. 定義 flexServiceRO
現在,就可以調用這個名為 flexServiceRO 的 RemoteObject 對象的方法了: 清單 14. 調用 FlexServiceRO.queryAll()
運行該 Flex Application,雇員信息已經被正確獲取了: 圖 7. 在瀏覽器中運行 Flex application ![]()
通過 RemoteObject 進行調用雖然簡單,但存在不少問題:首先,RemoteObject 是一個 Dynamic Class,Flex Builder 的編譯器無法替我們檢查參數類型和參數個數,這樣,在編寫 ActionScript 代碼時極易出錯。此外,接口變動時(這種情況常常發生),需要重新修改 RemoteObject 的定義。此外,Flex 團隊需要一份隨時修訂的完整的 FlexService 接口文檔才能工作。 因此,最好能使用強類型的 RemoteObject 接口,讓 Flex Builder 的編譯器及早發現錯誤。這個強類型的 RemoteObject 最好能通過 Java EE 應用的 FlexService 接口自動生成,這樣,就無需再維護 RemoteObject 的定義。 為了能完成自動生成 RemoteObject 對象,我編寫了一個 Java2ActionScript 的 Ant 任務來自動轉換 FlexService 接口以及相關的所有 JavaBean。JavaInterface2RemoteObjectTask 完成一個 Java 接口對象到 RemoteObject 對象的轉換。使用如下的 Ant 腳本: 清單 15. 生成 ActionScript class 的 Ant 腳本
轉換后的 FlexServiceRO 類擁有 Java 接口對應的所有方法,每個方法均為強類型簽名,并添加額外的兩個可選的函數處理 result 和 fault 事件。例如,queryByName 方法: 清單 16. 自動生成的 queryByName() 方法
轉換 Java 接口是通過 Interface.as 和 InterfaceMethod.as 兩個模板文件完成的,此外,所有在 Java EE 后端和 Flex 之間傳遞的 JavaBean 對象也通過 JavaBean2ActionScriptTask 自動轉換成對應的 ActionScript 類,這是通過 Bean.as 模板完成的。 有了 Java 類到 ActionScript 的自動轉換,我們在編寫 ActionScript 時,就能享受到編譯器檢查和 ActionScript 類方法的自動提示了: 圖 8. Flex Builder 的代碼自動補全 ![]() 唯一的缺憾是通過反射讀取 FlexService 接口時,我們失去了方法的參數名稱,因此,FlexServiceRO 的方法參數名只能變成 arg1,arg2 …… 等,要讀取 FlexService 接口的方法參數名,只能通過解析 Java 源代碼實現。 現在,Java EE 后端開發團隊和 Flex 前端開發團隊只需協商定義好 FlexService 接口,然后,利用 Java2ActionScript,Flex 團隊就得到了強類型的 FlexServiceRO 類,而 Java EE 團隊則只需集中精力實現 FlexService 接口。 在開發的前期,甚至可以用硬編碼的 FlexService 的實現類。每當 FlexService 變動時,只需再次運行 Ant 腳本,就可以獲得最新的 FlexServiceRO 類。這樣,兩個團隊都可以立刻開始工作,僅需要通過 FlexService 接口就可以完美地協同開發。
描述 名字 大小 下載方法 Java EE 工程源碼 Flex 工程源碼 Java2ActionScript 工程源碼
學習
獲得產品和技術
討論
|
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
