由於最近在 Java™ 服務器外觀(JSF)項目上工作,我很有幸第一次使用了 Facelets。關於 Facelets,我最喜歡的是它讓我可以創建可重用的復合組件。能夠拿出一個頁面(例如 JSP)並把它變成組件,對於我的 JSF 開發來說真是莫大的好處。我的結論是什麼?如果不用 Facelets,那麼就無法得到能從 JSF 獲得的最大收獲。
JSF 和 Java 服務器頁面技術之間的不匹配,是 JSF 開發中的一個嚴重問題。問題是如何把 JSP 的動態內容集成到 JSF 基於組件的模型中。JSP 非常重視生成動態內容輸出,而 JSF 需要 JSP 來協調組件模型的構建。因為這個任務超出了 JSP 原來的目的,所以產生了距離。
大多數 JSF 開發人員只是學會了一事一議地解決這類問題,但是這就像在錘子上放一個枕頭,最終還會掉下來打傷腦袋。Facelets 是更加全面的解決方案:專為 JSF 組件模型度身定制的模板化語言。
Facelets 有以下吸引人的特性:
◆模板化(像 Tiles)
◆復合組件
◆定制的邏輯標記
◆表達式語言
◆對設計師友好的頁面開發
◆創建組件庫
這些特性比我想像的要更相關和統一。在這篇文章中,我討論前兩個:模板化和復合組件。我使用的 Web 應用程序基於為我的針對懷疑者的 JSF 系列開發的一個應用程序,我把它更新成使用 Facelets 視圖而不是 Tiles。在進一步閱讀之前,應當 下載示例代碼。如果要隨著討論一起操作,還需要 安裝 Facelets。
Facelets 概述
對於 Facelets 可能會做的最大一個錯誤假設,就是它只是 Tiles 的替代品。Facelets 遠不止如此:它是思考 JSF 的新方式。
JSP 是種生成 servlet 的模板化語言。JSP 的主體與 servlet 的 doGet() 和 doPost() 方法等價(也就是說,成為 jspService() 方法)。JSF 定制標記(例如 f:vIEw 和 h:form)只是調用 JSF 組件來呈現它們自己的當前狀態。JSF 組件模型的生命周期獨立於 JSP 生成的 servlet 的生命周期。這種獨立性就是混淆的來源。
與 JSP 不同,Facelets 這個模板化語言,從構建之初,就考慮了 JSF 的組件生命周期。使用 Facelets,生成的模板會構建組件樹,而不是 servlet。這就允許更好的重用,因為可以把組件組合成另一個組件。
Facelets 減少了編寫定制標記才能使用 JSF 的需求。Facelets 本身就可以使用 JSF 定制組件。溝通 JSF 和 Facelets 只需要很少的特殊編碼:要做的全部工作就是在 Facelet 標記庫文件中聲明 JSF 組件。在 Facelets 模板化語言中可以直接使用 JSF 組件,不用任何額外的開發。
Facelets 模板框架
在提供針對組件構建設計的模板框架方面,Facelets 與 Tapestry (請參閱 參考資料)類似。但是,對於具有 JSP 背景的我們來說,Facelets 看起來比 Tapestry 友好得多。它允許使用熟悉的 JSTL 樣式的標記和 JSTL/JSF/JSP 樣式的表達式語言。大大降低的學習曲線意味著可以更加迅速地開始開發。
Facelets 允許定義能夠直接包含進頁面或者容易地添加到 Facelet 標記庫的組件集。實際上讓人高興的是在 Facelets 中定義定制標記(復合組件和類似 JSP 定制標記的標記)的迅速。使用這些組件集,Facelets 還允許定義站點模板(和更小的模板)。這與使用 Tiles 很相似,但是少了定義文件。也可以在定制 JSF 組件內部使用 Facelets,因為 Facelets API 提供了可以容易地與 JSF 組件集成的接口。
從 Tiles 到 Facelets
如前所述,在這裡使用的示例 Web 應用程序基於為我的 針對懷疑者的 JSF 系列創建的示例。它為一家在線 CD 店管理庫存,創建、讀取、更新和刪除(CRUD)清單。它包含一個表單,讓用戶向系統輸入新 CD,有一個單選按鈕列表,允許用戶選擇音樂分類。當用戶選擇了一個分類時,就觸發某些 JavaScript 立即把表單提交回服務器。應用程序還包含一個 CD 清單,用戶可以根據標題或藝術家對清單中的 CD 排序。
在線 CD 商店示例的類圖