Seam 是什麼?JBoss Seam 被定義為「Java EE 5.0 的一個輕量級框架」。Java EE 5.0 本身不就是一套框架嗎?為何在官方規範之外還需要另一個框架?不妨將 Seam 視為本應包含在 Java EE 5.0 中卻「遺漏」的框架。
Seam 位於 Java EE 5.0 框架之上,為企業級 Web 應用中的所有組件提供統一、易懂的程式設計模型,同樣讓基於狀態的應用與業務流程驅動的應用開發變得輕而易舉。換句話說,Seam 致力於提升開發者生產力與應用擴展性。
Java EE 5.0 核心框架為 EJB 3.0 與 JSF 1.2。EJB 3.0 基於 POJO 提供輕量級業務服務與資料庫持久化;JSF 是基於 MVC 的 Web 應用框架。大多數 Web 應用同時包含 EJB 3 業務組件與 JSF 前端組件。雖然兩者互補,但各自獨立設計:EJB 3 用註解配置服務,JSF 用 XML;組件在框架層面互不感知。整合它們需手動構建 Facade 物件(如 JSF 支援 Bean),將業務組件與 Web 頁面及樣板代碼連結。這正是 Seam 的職責之一。
Seam 打破 EJB 3 與 JSF 之間的人工屏障,提供一致的、基於註解的整合途徑。只需簡單註解,Seam 中的 EJB 3 業務組件即可直接支援 JSF Web 表單或處理 UI 事件。
Seam 允許開發者將「同一種東西」——帶註解的 POJO——應用於所有應用組件。與其他 Web 框架相比,Seam 應用概念簡潔,同樣功能所需代碼更少(Java 與 XML 均減少)。若想快速預覽 Seam 的簡潔性,可參考文中 Hello World 範例。
在 JSP 中棘手的任務,Seam 輕鬆搞定。例如 JSF 過度依賴 HTTP POST,導致書籤頁面難以透過 HTTP GET 訪問;有了 Seam,生成 REST 風格頁面極為容易。Seam 提供一系列 JSF 組件標籤與註解,增強「Web 友好」度與頁面效能。
同時,Seam 將 EJB 3 延伸至 POJO 組件模型,從 Web 層到業務層皆有狀態上下文。進一步說,Seam 整合了 jBPM、JBoss Rules (Drools)、JBoss Portal、JBoss Microcontainer 等主流開源框架,不僅「有機結合」,更能像強化 JSF 與 EJB 3 一樣強化原有框架。
Seam 雖建立於 Java EE 5.0 之上,但不限於 Java EE 5.0 伺服器。Seam 應用可部署於 J2EE 1.4 應用伺服器與 Tomcat,意味著當前即可獲得產品級支援。
1 + 1 > 2
或許有人誤以為 Seam 只是串聯各框架的整合框架。Seam 提供自身管理的狀態上下文,允許框架透過註解與 EL 表達式深度整合。整合邏輯源於 Seam 開發者對第三方框架的認知。
物件關係映射(ORM)在企業應用中廣泛使用,但大多數業務與 Web 框架並非為 ORM 設計,無法在整個 Web 交互生命週期(請求到響應)管理持久上下文。這導致可怕的 LazyInitializationException 等 ORM 異常,迫使開發者採用「資料傳輸物件(DTO)」等醜陋手段。
Gavin King 發明了 Seam,同時也是廣泛使用的 ORM 方案 Hibernate 的作者。為了傳承並發揚 ORM 最佳實踐,Seam 進行了重新設計。有了 Seam,不再需要寫 DTO,只需延遲載入。因為擴展後的持久上下文如同天然高速緩存,減少資料庫交互,ORM 效能大幅提升。
進一步說,Seam 整合 ORM 層、業務層與表示層,開發者可在表示層直接展示 ORM 物件,將資料庫驗證註解用於輸入表單,並將 ORM 異常重導向至自訂錯誤頁面。
Web 應用天生多用戶,電子商務應用天生有狀態且有事務。但大多數現有 Web 框架面向無狀態應用,開發者必須操作 HTTP Session 管理用戶狀態,無關業務邏輯的代碼不僅混亂應用,還帶來效能問題。
在 Seam 中,所有基礎應用組件天生有狀態,且由 Seam 公開管理,比 HTTP Session 更易用。無需編寫麻煩的狀態管理代碼——只需在組件上註解其作用域、生命週期方法與其他狀態屬性,Seam 便接管其餘。Seam 狀態組件比 HTTP Session 更善於管理用戶狀態:可在一個 HTTP Session 中擁有多個「會話」,每個由一系列 Web 請求與業務方法調用組成。
此外,資料庫緩存與事務能自動與應用狀態關聯。Seam 在記憶體中自動保存資料庫更新,對話結束後提交。記憶體緩存大幅減輕複雜狀態應用中資料庫的負載。
Seam 還支援整合開源 jBPM 業務流程引擎,大幅提升 Web 應用中的狀態管理。現可為機構中不同角色(客戶、經理、技術支援等)指定工作流程,以流程驅動應用,而非依賴 UI 事件與資料庫。
Seam 為 Web 2.0 應用充分優化。對 AJAX(異步 JavaScript 與 XML)提供多層支援——從內建「零 JavaScript」的 AJAX 組件、支援 AJAX 的 JSF 組件,到自訂 JavaScript 庫,Seam 為瀏覽器端 JavaScript 物件提供直接訪問伺服器端 Seam 組件的途徑。Seam 提供先進的並發模型,有效管理來自同一用戶的多個 AJAX 請求。
對 AJAX 應用,不斷增長的資料庫負載是巨大挑戰。相比非 AJAX 應用,AJAX 應用向伺服器發送更頻繁請求,資料庫若必須響應每個請求將不堪重負。Seam 的狀態持久上下文如同記憶體緩存,能在會話始末保存資訊,最終減少資料庫交互。
Web 2.0 應用常為資料使用複雜關係模型(如社交網站處理「用戶」間關係),延遲載入對 ORM 層至關重要,否則簡單查詢會級聯載入整個資料庫。正如前所述,Seam 是目前唯一正確支援 Web 應用延遲載入的 Web 框架。
Seam 是「輕量級」框架,因使用 POJO 作為服務組件。應用中 POJO 無需介面或抽象類「掛鉤」組件。那麼 POJO 如何交互組成應用?如何與容器服務(如資料庫持久化)交互?
Seam 透過依賴注入(DI)設計模式聯結所有 POJO 組件。框架管理所有組件生命週期。當一組件需使用另一組件時,透過註解向 Seam 宣告依賴。Seam 依據應用當前狀態取得依賴組件,並注入所需組件。
擴展 DI 概念,Seam 組件 A 不僅能構造組件 B,還能將 B「拋回」給 Seam 供其他組件(如 C)日後使用。這類雙向依賴管理甚至廣泛應用於簡單 Seam Web 應用(如第二章 Hello World 範例)。Seam 術語稱之為「依賴雙向映射」。
使 Seam 易用的主要設計原則是「慣例優於配置」。思想是為組件提供一系列預設行為,開發者僅在預期行為非預設時顯式配置。例如,Seam 將組件 A 作為屬性注入組件 B 時,預設以 B 被注入屬性的名稱命名 A。Seam 還有許多類似細節。總結果是 Seam 配置元資料比其他 Java 框架簡單得多。大多數 Seam 應用僅需一系列簡單 Java 註解即可充分配置。開發者從降低的複雜度受益,最終以更少代碼實現同樣功能。
Java 註解在表述與處理 Seam 配置元資料時扮演關鍵角色,使框架更易操作。
J2EE 早期,XML 被視為配置管理的「聖杯」。框架設計者將所有配置資訊(含 Java 類與方法名)統統塞進 XML,不顧對開發者的後果。事後證明這是嚴重錯誤。XML 配置文件嚴重重複,開發者必須重複代碼中已有的資訊以連結配置與代碼。這些重複易導致錯誤(如拼寫錯誤的類名在運行時顯示為難除錯的錯誤)。缺乏合理預設配置進一步複雜化問題。事實上,一些框架中相當數量的樣板代碼偽裝為 XML,可能等於或超過實際 Java 代碼量。對 J2EE 開發者,XML 濫用常稱為「XML 地獄」。
Java 社區已認識到此問題,並成功以 Java 代碼中的註解取代 XML。EJB 3 是 Java 官方標準化機構推動企業組件中註解使用的成果。EJB 3 完全可選擇使用 XML,邁出積極一步。Seam 加入 EJB 3 註解,為整個 Web 應用延伸基於註解的程式設計模型。
當然,XML 對配置資料並非完全無利。Seam 設計者認識到 XML 適用於指定頁面流程或定義業務流程的 Web 應用。XML 文檔使開發者集中管理整個 Web 應用工作流程成為可能,同時反對將配置資訊分散於 Java 源文件。工作流程很少與源代碼耦合,因此 XML 中無需重複輸入代碼中已有的資訊。
Seam 為易於測試而重新設計。因所有 Seam 組件皆為帶註解的 POJO,易於進行單元測試。開發者僅需利用 Java new 關鍵字構造實例,然後在測試框架(如 JUnit 或 TestNG)中運行任意方法。若需測試多個 Seam 組件交互,開發者逐個實例化組件,再手動建立其相互關係(即顯式使用 setter 方法,而非依賴 Seam DI)。
整合測試整個 Seam 應用較複雜,因需在 Seam 容器中運行。Seam 提供嵌入式輕量級容器協助此類測試。在測試框架中,開發者可逐步載入 Seam 容器,然後運行測試。
希望以上八大面向的介紹能幫助你理解 Seam 的價值。