Struts2源码阅读(二)_ActionContext及CleanUP Filter
1. ActionContext
ActionContext是被存放在當(dāng)前線程中的,獲取ActionContext也是從ThreadLocal中獲取的。所以在執(zhí)行攔截器、 action和result的過程中,由于他們都是在一個(gè)線程中按照順序執(zhí)行的,所以可以可以在任意時(shí)候在ThreadLocal中獲取 ActionContext。
ActionContext包括了很多信息,比如Session、Application、Request、Locale、ValueStack等,其中 ValueStack可以解析ognl表達(dá)式,來動(dòng)態(tài)后去一些值,同時(shí)可以給表達(dá)式提供對象。
?
ActionContext(com.opensymphony.xwork.ActionContext)是Action執(zhí)行時(shí)的上下文,上下文可以看作是一個(gè)容器 (其實(shí)我們這里的容器就是一個(gè)Map而已),它存放的是Action在執(zhí)行時(shí)需要用到的對象. 一般情況, 我們的ActionContext都是通過: ActionContext context = (ActionContext) actionContext.get(); 來獲取的.我們再來看看這里的actionContext對象的創(chuàng)建:
static ThreadLocal actionContext = new ActionContextThreadLocal();
ActionContextThreadLocal是實(shí)現(xiàn)ThreadLocal的一個(gè)內(nèi)部類.ThreadLocal可以命名為"線程局部變量",它為每一個(gè)使用該變量的線程都提供一個(gè)變量值的副本,使每一個(gè)線程都可以獨(dú)立地改變自己的副本,而不會(huì)和其它線程的副本沖突.這樣,我們 ActionContext里的屬性只會(huì)在對應(yīng)的當(dāng)前請求線程中可見,從而保證它是線程安全的.
通過ActionContext取得HttpSession: Map session = ActionContext.getContext().getSession(); (通過Map模擬HttpServlet的對象,操作更方便)
?
2. ServletActionContext
ServletActionContext(com.opensymphony.webwork. ServletActionContext),這個(gè)類直接繼承了我們上面介紹的ActionContext,它提供了直接與Servlet相關(guān)對象訪問的功能,它可以取得的對象有:
(1)javax.servlet.http.HttpServletRequest : HTTPservlet請求對象?
(2)javax.servlet.http.HttpServletResponse : HTTPservlet相應(yīng)對象?
(3)javax.servlet.ServletContext : Servlet上下文信息?
(4)javax.servlet.ServletConfig : Servlet配置對象?
(5)javax.servlet.jsp.PageContext : Http頁面上下文
如何從ServletActionContext里取得Servlet的相關(guān)對象:
<1>取得HttpServletRequest對象: HttpServletRequest request = ServletActionContext. getRequest();
<2>取得HttpSession對象: HttpSession session = ServletActionContext. getRequest().getSession();
?
3. ServletActionContext和ActionContext聯(lián)系
ServletActionContext和ActionContext有著一些重復(fù)的功能,在我們的Action中,該如何去抉擇呢?我們遵循的原則是:如果ActionContext能夠?qū)崿F(xiàn)我們的功能,那最好就不要使用ServletActionContext,讓我們的Action盡量不要直接去訪問Servlet的相關(guān)對象.
注意:在使用ActionContext時(shí)有一點(diǎn)要注意: 不要在Action的構(gòu)造函數(shù)里使用ActionContext.getContext(), 因?yàn)檫@個(gè)時(shí)候ActionContext里的一些值也許沒有設(shè)置,這時(shí)通過ActionContext取得的值也許是null;同樣,HttpServletRequest req = ServletActionContext.getRequest()也不要放在構(gòu)造函數(shù)中,也不要直接將req作為類變量給其賦值。 至于原因,我想是因?yàn)榍懊嬷v到的static ThreadLocal actionContext = new ActionContextThreadLocal(),從這里我們可以看出ActionContext是線程安全的,而 ServletActionContext繼承自ActionContext,所以ServletActionContext也線程安全,線程安全要求每個(gè)線程都獨(dú)立進(jìn)行,所以req的創(chuàng)建也要求獨(dú)立進(jìn)行,所以ServletActionContext.getRequest()這句話不要放在構(gòu)造函數(shù)中,也不要直接放在類中,而應(yīng)該放在每個(gè)具體的方法體中(eg:login()、queryAll()、insert()等),這樣才能保證每次產(chǎn)生對象時(shí)獨(dú)立的建立了一個(gè)req。
?
4.ActionContextClearUp
ActionContextClearUp其實(shí)是Defer ClearUP.作用就是延長action中屬性的生命周期,包括自定義屬性,以便在jsp頁面中進(jìn)行訪問,讓actionContextcleanup過濾器來清除屬性,不讓action自己清除。具體看下面的代碼,代碼很簡單:
public void doFilter(...){ ... try{ ... //繼續(xù)執(zhí)行所配置的chain中的Filter chain.doFilter(request, response); }finally{ //保證在所有動(dòng)作執(zhí)行完之后,調(diào)用cleanUp ... cleanUp(request); } } protected static void cleanUp(ServletRequest req) { ... ActionContext.setContext(null);//清除ActionContext實(shí)例 Dispatcher.setInstance(null);//清除Dispatcher實(shí)例(Dispatcher主要是完成將url解析成對應(yīng)的Action) } 另外注明一下UtilTimerStack的push和pop是用來計(jì)算調(diào)用方法所執(zhí)行的開始和結(jié)束時(shí)間,用來做性能測試的。用法如下:
String timerKey = "ActionContextCleanUp_doFilter: "; UtilTimerStack.setActive(true); UtilTimerStack.push(timerKey); //調(diào)用要測試的方法。 UtilTimerStack.pop(timerKey);
總結(jié)
以上是生活随笔為你收集整理的Struts2源码阅读(二)_ActionContext及CleanUP Filter的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Data JPA 从入门到
- 下一篇: java调用shell脚本并传递参数