在值棧(前篇)我們學習了值棧的基本知識,接下來,來看看在程序中具體如何使用值棧。
1 ActionContext的基本使用
1.1 如何獲取?
要獲取ActionContext有兩個基本的方法,如果在不能獲取到ActionInvocation的地方,可以直接使用ActionContext一個靜態的getContext方法,就可以訪問到當前的ActionContext了,示例如下:
ActionContext ctx = ActionContext.getContext();
如果在能獲取到ActionInvocation的地方,比如在攔截器里面、自定義的Result里面等,可以通過ActionInvocation來獲取到ActionContext,示例如下:
ActionContext ctx = actionInvocation.getInvocationContext();
1.2 獲取過后,如何使用?
ActionContext主要的功能是用來存放數據的,典型的方法如下:
- get(String key):根據key從ActionContext當前的存儲空間里面獲取相應的值
- put(String key, Object value):把值存儲在ActionContext的存儲空間里面
- Map<String,Object> getApplication():返回ServletContext中存儲的值
- Map<String,Object> getSession():返回HttpSession中存儲的值
- Map<String,Object> getContextMap():返回當前context存儲的值
- Map<String,Object> getParameters():返回HttpServletRequest對象里面存儲的,客戶端提交的參數
- ValueStack getValueStack():獲取OGNL的值棧
對於getXXX的方法,都有對應的setXXX方法,這里就不去贅述了,具體的請參看Struts2的API文檔。
1.3 應用示例
在《自定義更強大的logger攔截器》和《自定義登陸驗證攔截器》中,兩個攔截器都使用了ActionContext對象,詳細請查看這兩篇文章。
2 ValueStack的基本使用
在值棧(前篇)中,我們看到了ValueStack被包含在ActionContext中,ValueStack也是用來存儲對象的,但是它主要是通過OGNL表達式來訪問,也就是說,在Struts2里面主要是通過標簽來訪問的。ValueStack有一個特點,如果訪問的值棧里有多個對象,且相同的屬性在多個對象中同時出現,則值棧會按照從棧頂到棧底的順序,尋找第一個匹配的對象。
2.1 如何獲取?
直接由ActionContext對象的getValueStack()方法即可獲取
2.2 如何使用?
ValueStack主要的功能也是用來存放數據的,典型的方法如下:
- Object findValue(String expr):根據表達式在value stack中,按照缺省的訪問順序去獲取表達式對應的值
- void setValue(String expr, Object value):根據表達式,按照缺省的訪問順序,向value stack中設置值
- Object peek():獲取value stack中的頂層對象,不修改value stack對象
- Object pop():獲取value stack中的頂層對象,並把這個對象從value stack中移走
- void push(Object o):把對象加入到value stack對象中,並設置成為頂層對象
2.3 應用示例
前面的示例中,歡迎頁面顯示的帳號,是從登錄頁面填寫並傳遞到后台的數據,假如現在想要修改在歡迎頁面顯示的帳號數據,但是前面從登錄頁面填寫並傳遞到后台的數據不需要變化,那么該怎么實現呢?先來分析一下,要想修改result頁面顯示的值,肯定需要在Result處理之前修改這個值,否則等Result處理完成過后再改就沒有意義了。因此,可以選用PreResultListener的技術,在里面把值修改好,然后再進行Result處理。另外一點,在歡迎頁面是通過標簽來獲取帳號的數據並展示的,也就是說值的來源是value stack,因此,在PreResultListener里面要修改的就是value stack里面的值。好了,清楚該干什么過后,來具體看看示例。
1)先來實現PreResultListener,在里面修改value stack里面的值,示例如下:
public class MyPreResult implements PreResultListener{ public void beforeResult(ActionInvocation actionInvocation, String result) { System.out.println("現在處理Result執行前的功能,result="+result); actionInvocation.getInvocationContext().getValueStack().setValue("account", "被修改了"); } }
2)實現了PreResultListener,還需要在運行之前注冊,這里選擇在Action里面來注冊這個監聽器,示例如下:
public class HelloWorldAction extends ActionSupport { private String account; private String password; private String submitFlag; public String execute() throws Exception { this.businessExecute(); ActionContext c = ActionContext.getContext(); MyPreResult pr = new MyPreResult(); c.getActionInvocation().addPreResultListener(pr); return "toWelcome"; } /** * 示例方法,表示可以執行業務邏輯處理的方法, */ public void businessExecute(){ System.out.println("用戶輸入的參數為==="+"account="+account+",password="+password+",submitFlag="+submitFlag); } //屬性對應的getter/setter方法,省略了 }
3)struts.xml、登陸界面和歡迎界面都不變。歡迎界面中的<s:property value="account"/>就可以獲得MyPreResult類中修改的account值了。
由於通常情況下,向value stack里面壓入值都是由Struts2去完成,而訪問value stack多是通過標簽中的OGNL表達式,因而直接使用ValueStack的機會並不是很多。
參考資料:http://www.iteye.com/topic/1124526