1. ActionContext
ActionContext是被存放在當前線程中的,擷取ActionContext也是從ThreadLocal中擷取的。所以在執行攔截器、 action和result的過程中,由於他們都是在一個線程中按照順序執行的,所以可以可以在任意時候在ThreadLocal中擷取 ActionContext。
ActionContext包括了很多資訊,比如Session、Application、Request、Locale、ValueStack等,其中 ValueStack可以解析ognl運算式,來動態後去一些值,同時可以給運算式提供對象。
ActionContext(com.opensymphony.xwork.ActionContext)是Action執行時的上下文,上下文可以看作是一個容器 (其實我們這裡的容器就是一個Map而已),它存放的是Action在執行時需要用到的對象. 一般情況, 我們的ActionContext都是通過: ActionContext context = (ActionContext) actionContext.get(); 來擷取的.我們再來看看這裡的actionContext對象的建立:
static ThreadLocal actionContext = new ActionContextThreadLocal();
ActionContextThreadLocal是實現ThreadLocal的一個內部類.ThreadLocal可以命名為"線程局部變數",它為每一個使用該變數的線程都提供一個變數值的副本,使每一個線程都可以獨立地改變自己的副本,而不會和其它線程的副本衝突.這樣,我們 ActionContext裡的屬性只會在對應的當前請求線程中可見,從而保證它是安全執行緒的.
通過ActionContext取得HttpSession: Map session = ActionContext.getContext().getSession(); (通過Map類比HttpServlet的對象,操作更方便)
2. ServletActionContext
ServletActionContext(com.opensymphony.webwork. ServletActionContext),這個類直接繼承了我們上面介紹的ActionContext,它提供了直接與Servlet相關對象訪問的功能,它可以取得的對象有:
(1)javax.servlet.http.HttpServletRequest : HTTPservlet請求對象
(2)javax.servlet.http.HttpServletResponse : HTTPservlet相應對象
(3)javax.servlet.ServletContext : Servlet上下文資訊
(4)javax.servlet.ServletConfig : Servlet設定物件
(5)javax.servlet.jsp.PageContext : Http頁面上下文
如何從ServletActionContext裡取得Servlet的相關對象:
<1>取得HttpServletRequest對象: HttpServletRequest request = ServletActionContext. getRequest();
<2>取得HttpSession對象: HttpSession session = ServletActionContext. getRequest().getSession();
3. ServletActionContext和ActionContext聯絡
ServletActionContext和ActionContext有著一些重複的功能,在我們的Action中,該如何去抉擇呢?我們遵循的原則是:如果ActionContext能夠實現我們的功能,那最好就不要使用ServletActionContext,讓我們的Action盡量不要直接去訪問Servlet的相關對象.
注意:在使用ActionContext時有一點要注意: 不要在Action的建構函式裡使用ActionContext.getContext(), 因為這個時候ActionContext裡的一些值也許沒有設定,這時通過ActionContext取得的值也許是null;同樣,HttpServletRequest req = ServletActionContext.getRequest()也不要放在建構函式中,也不要直接將req作為類變數給其賦值。 至於原因,我想是因為前面講到的static ThreadLocal actionContext = new ActionContextThreadLocal(),從這裡我們可以看出ActionContext是安全執行緒的,而 ServletActionContext繼承自ActionContext,所以ServletActionContext也安全執行緒,安全執行緒要求每個線程都獨立進行,所以req的建立也要求獨立進行,所以ServletActionContext.getRequest()這句話不要放在建構函式中,也不要直接放在類中,而應該放在每個具體的方法體中(eg:login()、queryAll()、insert()等),這樣才能保證每次產生對象時獨立的建立了一個req。
4.ActionContextClearUp
ActionContextClearUp其實是Defer ClearUP.作用就是延長action中屬性的生命週期,包括自訂屬性,以便在jsp頁面中進行訪問,讓actionContextcleanup過濾器來清除屬性,不讓action自己清除。具體看下面的代碼,代碼很簡單:
public void doFilter(...){ </p><p> ...<br /> try{<br /> ...<br /> //繼續執行所配置的chain中的Filter<br /> chain.doFilter(request, response);<br /> }finally{<br /> //保證在所有動作執行完之後,調用cleanUp<br /> ...<br /> cleanUp(request);<br /> }<br />} </p><p>protected static void cleanUp(ServletRequest req) { </p><p> ...<br /> ActionContext.setContext(null);//清除ActionContext執行個體<br /> Dispatcher.setInstance(null);//清除Dispatcher執行個體(Dispatcher主要是完成將url解析成對應的Action)<br />}<br />
另外註明一下UtilTimerStack的push和pop是用來計算調用方法所執行的開始和結束時間,用來做效能測試的。用法如下:
String timerKey = "ActionContextCleanUp_doFilter: "; </p><p>UtilTimerStack.setActive(true); </p><p>UtilTimerStack.push(timerKey);<br />//調用要測試的方法。<br />UtilTimerStack.pop(timerKey);
Come From: http://qidaoxp.javaeye.com/blog/492387