Posted on 2010-05-28 23:33
Gavin.lee 閱讀(770)
評論(0) 編輯 收藏 所屬分類:
SSH2 --Struts2
Struts2 處理流程概要:
一個請求在Struts2框架中的處理大概分為以下幾個步驟
1 客戶端初始化一個指向Servlet容器(例如Tomcat)的請求
2 這個請求經過一系列的過濾器(Filter)(這些過濾器中有一個叫做ActionContextCleanUp的可選過濾器,這個過濾器對于Struts2和其他框架的集成很有幫助,例如:SiteMesh Plugin)
3 接著FilterDispatcher被調用,FilterDispatcher詢問ActionMapper來決定這個請是否需要調用某個Action
4 如果ActionMapper決定需要調用某個Action,FilterDispatcher把請求的處理交給ActionProxy
5 ActionProxy通過Configuration Manager詢問框架的配置文件,找到需要調用的Action類
6 ActionProxy創建一個ActionInvocation的實例。
7 ActionInvocation實例使用命名模式來調用,在調用Action的過程前后,涉及到相關攔截器(Intercepter)的調用。
8一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果。返回結果通常是(但不總是,也可能是另外的一個Action鏈)一個需要被表示的JSP或者FreeMarker的模版。在表示的過程中可以使用Struts2框架中繼承的標簽。在這個過程中需要涉及到ActionMapper,在上述過程中所有的對象(Action,Results,Interceptors,等)都是通過ObjectFactory來創建的。
過濾器介紹(Filter)
FilterDispatcher(注:我所使用的2.1.8版本中過濾器也升級到了StrutsPrepareAndExecuteFilter)
org.apache.struts2.dispatcher.FilterDispatcher的四個功能(必須)
struts2.0的主要Filter,負責四個方面的功能。具體:
(1)執行Actions
過濾器通過ActionMapper對象,來判斷是否應該被映射到Action.如果mapper對象指示他應該被映射,過濾鏈將會被終止,然后Action被調用。這一點非常重要,如果同時使用SiteMesh filter,則SiteMesh filter應該放到該過濾器前,否則Action的輸出將不會被裝飾。
(2)清除ActionContext
過濾器為了確保內存溢出,會自動的清除ActionContext。這可能會存在一些問題,在和其它的框架集成時,例如SiteMesh。ActionContextCleanUp提供了怎么處理這些問題的一些信息。
(3)維護靜態內容
過濾器也會維護在Struts2中使用的一些公共的靜態的內容,例如JavaScript文件,CSS文件等。搜索/struts/*范圍內的請求,然后將/struts/后面的值映射到一些struts的公共包中,也可以在你的類路徑中搜索。
(4)清除ActionContext中的內容。
Finally{ActionContextCleanUp.cleanUp(req);}
ActionContextCleanUp
org.apache.struts2.dispatcher.ActionContextCleanUp(可選)
可選過濾器,這個過濾器對于Struts2和其他框架的集成很有幫助,例如:SiteMesh Plugin。該過濾器用來與FilterDispatcher協同工作以便于集成SiteMesh. 通常, 排列過濾器并保證SiteMesh排在第一位, 而讓FilterDispatcher排在第二位看起來是最佳方案. 然而, 你可能希望在SiteMesh修飾器中使用WebWork的特性, 包括value stack, 但由于FilterDispatcher將清除ActionContext, 因此修飾器就訪問不到想要的數據了.
WEB.XML配置順序
在WebWork的架構中, 標準的過濾器鏈(filter-chain)一般以 ActionContextCleanUp 開始, 后面跟著其他需要的過濾器. 最后, 由 FilterDispatcher 處理請求, 通常是將請求傳遞給ActionMapper. ActionContextCleanUp 的首要用途是為集成SiteMesh服務的. 他會通知FilterDispatcher在正確的時間清除請求. 否則, ActionContext將在SiteMesh修飾器訪問數據之前被清除.
在不使用SiteMesh的時候,為了使用WebWork,我們只需要在web.xml配置FilterDispatcher一個過濾器即可,閱讀一下FilterDispatcher的JavaDoc和源碼,我們可以看到它調用了:
finally { ActionContextCleanUp.cleanUp(req); }
而且JavaDoc中也提到看ActionContextCleanUp的文檔,那我們就去看吧(我沒看所以...)
在ActionContextCleanUp中,有這樣的代碼:
req.setAttribute(CLEANUP_PRESENT, Boolean.TRUE);
如果FilterDispatcher檢測到這個屬性,就不會清除ActionContext中的內容了,而由ActionContextCleanUp后續的代碼來清除,保證了一系列的Filter訪問正確的ActionContext.文檔中提到,如果用到SiteMesh的Filter或者其他類似Filter,那么設置順序是:
1 ActionContextCleanUp filter
2 SiteMesh filter
3 FilterDispatcher
Struts 2 中使用的模式--CHAIN OF RESPONSIBILITY(職責鏈)
適用性:
1.有多個對象可以處理統一請求,但是,那個對象處理要到運行時刻決定。
2.希望在不明確接收者的情況下,向多個對象中的一個提交一個請求。
3.可處理一個請求的對象集合應該被動態指定。
思考:
既然要向未知的接收者提交請求,那么就需要統一的提交界面,也就是說,所有接收者應該實現一個公共接口,來接收請求,當然Delegate可以改變這一狀況。一個典型的應用環境就是GUI系統中的事件處理方法。例如,我們可以定義一個OnClick的界面,然后OnClick可以是實際接收對象的一個方法代理:
OnClick = someObj.doClick;
最重要的是,OnClick和someObj.doClick之間的關系是可以動態改變的。另外,這個doClick可以向一個對象集合分發該事件,該集合也是可以動態變化的,這時它的靜態結構和觀察員模式很相似,但是職責鏈模式并不需要將事件遞交給每一個接收者。觀察員模式關心的是如何觀察到模型的變化,職責鏈模式關心的是如何遞交出事件。這兩者還都需要關心如何接收到相應的事件,盡管接收的行為并不一樣。
職責鏈模式需要關心每一個事件都應該被合適的一個或多個接收者處理(HOOK模式)。例如,在一個消息分派的過程中,我們需要考慮如何增減消息處理過程,以處理相關的消息,通常這些處理過程都是各不相同的行為,并且反過來可能對發送者有影響。觀察員模式一般而言,應該是無擾的。
接收者常常是通過Composite模式來組織的。
COMMAND(命令)
適用性:
1.Command模式是回調函數的一個面向對象的替代品。
2.Command對象可以有和初始請求無關的生存期
3.支持取消操作
4.支持修改日志
5.用構建在原語操作上的高層操作構造一個系統。
思考:
COMMAND模式總是會關聯到一個觸發者。通常,它提供的是一個非常簡單的接口。COMMAND對象一般而言是一個相對高級的對象,他通常可以完成一個相對完整的概念操作,好像是完成了一個事務一樣。因為COMMAND比較高級,那么其內部可以安排一些相對底層的支持,例如日志活動。很多COMMAND對象也是同時提供撤銷操作。
如果COMMAND應用于事務系統,并且,一個COMMAND對象對應于一個事務的話,要小心撤銷語意。一般而言,不應該撤銷一個事務系統中已經完成的事務。而是通過另一個反向的事務來沖抵。例如一個帳務系統,對于錯誤的記帳流水事務,在向系統提交以前,可以簡單撤銷(這可以在Command對象的撤銷操作中實現,也可以簡單放棄)。對于提交以后,則應該提供一個反向的撤銷流水事務(不建議在撤銷操作中實現),這樣系統最終記錄兩個事務,并且后一個事務可以沖銷前一個事務。進一步,如果發現歷史帳務流水記錄有錯,一般的財務邏輯是需要用紅字沖正,就更不應該采用撤銷的手段了。
職責鏈的接收者,可以實現為COMMAND對象,當然,這并不必要。