(摘自《Expert One-on-OneJ2EE Development without EJB》第13章 Alternative Approaches to Web MVC)
雖然當前流行的是基于請求驅動的Web MVC框架,但在J2EE中還有兩種比較重要的替代開發方法:Portlets和基于事件驅動的Web MVC框架。
1、Portals和Portlets
(1)概述
l Web Portal由多個完全不相關的部分組成的單個HTML頁面實現,每個部分由controller-view組件實現
l Portal容器是由工作流控制的
l controller-view組件在Portal中稱為Portlet
l 每個Portlet是一個自交互的組件,而不是一個工作流控制的下級代表
l Portlet就像MVC的控制器一樣,接收表示請求,檢查請求參數,創建數據模型,轉向顯示視圖
(2)JSR168
l JSR168是Java的Portlet規范,定義了類似于Servlet的API和環境:javax.portlet.Portlet
l 不同于Servlet,Portlet不是一個響應HTTP請求處理的組件,而是通過Portal容器的工作流處理器獲得通知,響應各種命令的回調組件:
? doView(RenderRequest, RenderResponse):顯示Portlet缺省視圖
? doEdit(RenderRequest, RenderResponse):顯示Portlet編輯視圖(如果支持的話)
? doHelp(RenderRequest, RenderResponse):顯示Portlet幫助視圖(如果支持的話)
? processAction(ActionRequest, ActionResponse):在Portlet提交請求給自己時,由容器調用(對于任何視圖模式)
l 在一個典型的JSR168 Portlet中,doView充當組件控制器,準備數據模型,可能訪問中間層資源和服務,轉向到作為Portlet視圖的JSP
l 自遷移的表單提交,使用標準的HTML <form>標記,使用Portlet的<portlet:actionURL>標記指定其action屬性,Portlet容器會使用提交的參數來調用processAction,通過返回視圖模式來調用doView、doEdit或doHelp
(3)部署Portlet
l Portlet集合以標準的WAR文件部署,只是Portlet的定義在/WEB-INF/portlet.xml中,而不是使用web.xml
(4)共享
l Portlet規范定義了它自己的MVC機制,來適應自包含Portlet的需求
l 如果Portlet容器在J2EE服務器中運行,Portlet可以通過JNDI來訪問中間層的資源和服務
l 但是,Portlet看上去不可能向Web應用程序的其它組件共享本地資源,因為它們位于獨立的環境
2、事件驅動的Web MVC框架
(1)概述
l 事件驅動框架的目標是應用桌面UI編程到Web環境
l 它們不把焦點集中在表單提交到依次映射到控制器進行請求處理的URL,而是把表單組件關聯到由事件調用的監聽器
l 它們通常不把焦點集中呈現給定模型對象的嵌入式視圖技術,而是將Web頁面作為保持狀態和知道任何應用不同的皮膚呈現自己的組件集合
l 象Echo和WingS這樣的框架,提供接近Swing的編程模型,由UI組件類生成實際的HTML代碼,這使得Web設計者不容易進行定制,限制了定制HTML和JavaScript的靈活集成,而且會生成出大量不需要的會話狀態
l 其它框架象Typestry和JSF(JSR127)結合了模板方法和事件處理機制:HTML布局在模板(如JSP和Velocity)中定義,實際的工作流和視圖呈現由處理頁面中表單組件事件的框架控制器管理
l 后來的基于模板的方法在一定程度上受到微軟的ASP.NET,象JSF在很多方面就像是Java世界中的ASP.NET
(2)Typestry
l Typestry將焦點集中在完全分離的Java代碼和HTML模板,將每個頁面分成3個部分:
? HTML模板:純HTML標記,包含由jwcid屬性標記的動態部分
? 頁面規范:定義頁面實現類和頁面中使用的組件
? 頁面類:定義模型和頁面的監聽器
l 每個頁面由任意數量和嵌套的組件組成,每個組件同樣被分成類似的3個部分:
? HTML模板:用于組件的純HTML標記,包含由jwcid屬性標記的動態部分
? 頁面規范:定義組件實現類和使用的嵌套組件
? 頁面類:定義模型和組件的監聽器
l Typestry的HTML模板不包含腳本和自定義標記,而是由jwcid(Java Web組件ID)屬性標識的特定標記,典型的標記是<span jwcid=”…”>,在運行期,這些標記會被Typestry組件生成的HTML代碼替代
l Typestry的HTML模板可以在瀏覽器和HTML編輯器中顯示,非標準的jwcid屬性標記會被忽略
l Typestry的HTML模板和JSP或Velocity使用標記代碼、動態表達式和控制流邏輯實現的動態視圖不同,是靜態模板,需要使用頁面規范合成來產生實際的動態視圖
l Typestry會處理所以的工作流管理,而不需要接觸HttpServletRequest 或 HttpServletResponse
l 表單提交的數據綁定到頁面或組件實例的屬性(Model),控制邏輯由頁面或組件類的監聽器實現,執行某個動作或轉到不同頁面(Controller)
l Typestry的頁面實例是pooled;頁面屬性如果需要對相同用戶在不同頁面之間保持狀態,可以標記為持久,Typestry會將頁面屬性保存到HttpSession中
l Typestry應用程序需要一個應用程序規范來定義有效的頁面,也決定被使用的引擎類
l 引擎類是服務器端的狀態管理器,通常保存在HttpSession中保持兩種類型的應用程序特定狀態對象:
? Visit對象:包含當前訪問用戶關聯的所有狀態,對應于HttpSession屬性
? Global對象:為應用程序的所有引擎實例共享,對應于ServletContext屬性
l 和頁面一樣,引擎實例是pooled
(3)JSF
l JSF將焦點集中在使用JSP標記庫創建表單,在JSP代碼中嵌入驗證器和導航規則的引用
l 驗證器、導航規則和被管理Bean(如表單對象)在faces-config.xml中定義
l JSF視圖通過FacesServlet被調用(View)
l Action由命令風格的事件監聽器實現,被調用后返回字符串結果,通常是轉向視圖的導航規則引用,可以通過FacesContext訪問它們的環境中的對象(Controller)
l 表單對象是簡單的JavaBean(Model)
l 組件由自定義標記實現,可以通過不同的插件式呈現器改變皮膚,這就允許重用相同的JSF視圖到不同的目標格式,如HTML和WML(視圖無關模型)
3、各種Java/J2EE方案的選擇
l ASP風格的腳本編程:純JSP
l CGI風格的請求處理:Servlet,主要是二進制內容
l 基于Servlet/JSP的自定義MVC方案:簡單工作流
l 使用JSP的請求驅動Web MVC框架:Struts、WebWork等(很多選擇)
l 使用Velocity、Freemarker等模板引擎的請求驅動Web MVC框架
l 使用XSLT、XMLC等XML技術的請求驅動Web MVC框架
l Swing風格呈現GUI組件:Echo、WingS
l 基于頁面規范的GUI創建:Typestry
l ASP.NET風格的GUI創建:JSF