java值栈_Struts2 中的值栈是什么?
7.1值棧
7.1.1值棧是什么
簡單的說:值棧是對應每一個請求對象的輕量級的內存數據中心。
Struts2中一個很激動人心的特性就是引入了值棧,在這里統一管理著數據,供Action、Result、Interceptor等Struts2的其他部分使用,這樣一來,數據被集中管理起來而不會凌亂,大大方便了程序編寫。
Struts2中關于值棧的另外一個很激動人心的特性就是:大多數情況下,你根本無需關心值棧,你不用管它在哪里,不用管它里面有什么,你只需要去獲取自己需要的數據就可以了。也就是說,你可以隱式的使用值棧。
當然,如果編寫自定義的Result或攔截器等較復雜功能的時候,還是需要顯示訪問值棧的,因此,還是需要你掌握值棧的知識。
7.1.2值棧能干什么
簡單的說,值棧能夠線程安全的為每個請求提供公共的數據存取服務。
當有請求到達的時候,Struts2會為每個請求創建一個新的值棧,也就是說,值棧和請求是一一對應的,不同的請求,值棧也不一樣,而值棧封裝了一次請求所有需要操作的相關的數據。
正是因為值棧和請求的對應關系,因而值棧能保證線程安全的為每個請求提供公共的數據存取服務。
7.1.3值棧有什么
事實上,到現在為止,我們一直在講“值棧”,這種說法其實是不夠準確的。為什么呢?因為在Struts2中,值棧又有廣義和狹義之分:
1:狹義值棧
通常指的是實現com.opensymphony.xwork2.util.ValueStack接口的對象,目前就是com.opensymphony.xwork2.ognl.OgnlValueStack對象。
狹義值棧主要用來存取動態EL(表達式語言)運算需要的值和結果,當然OgnlValueStack對象主要是用來支持OGNL(對象圖導航語言)運算的。
狹義值棧里面存放著一些OGNL可以存取訪問的數據,典型如:Action的實例,這樣就可以通過OGNL來訪問Action實例中的屬性的值了
OGNL表達式運算的值,可以設置到值棧中,可以主動訪問值棧對象,強行設置
OGNL表達式產生的中間變量,比如在后面使用Struts2的標簽的時候,使用循環標簽,自然會有循環的變量,這些都存放在值棧中
2:廣義值棧
通常指的是ActionContext對象,ActionContext是Action運行的上下文,每個ActionContext是一個基本的容器,包含著Action運行需要的數據,比如請求參數、會話等。
ActionContext是線程安全的,每個線程有一個獨立的ActionContext,這樣你就不用擔心值棧中值的線程安全問題了。
ActionContext里面存放有很多的值,典型如:Request的parameters:請求中的參數,要注意這里的數據是從請求對象里面拷貝出來的,因此這里數據的變化是不會影響到請求對象里面的參數的值的
Request的Attribute:請求中的屬性,這里其實就是個Map,存放著請求對象的屬性數據,這些數據和請求對象的Attribute是連動的
Session的Attribute:會話中的屬性,這里其實就是個Map,存放著會話對象的屬性數據,這些數據和會話對象的Attribute是連動的
Application的Attribute:應用中的屬性,這里其實就是個Map,存放著應用對象的屬性數據,這些數據和應用對象的Attribute是連動的
Value stack:也就是狹義值棧,ActionContext以value stack作為被OGNL訪問的根,簡單點說,OGNL在沒有特別指明的情況下,訪問的就是value stack里面的數據
attr:在所有的屬性范圍中獲取值,依次搜索page、request、session和application。
前面已經了解到Xwork與Web是無關的,因此Action不用去依賴于任何Web容器,不用和Servlet 的API去交互,但是Action需要能訪問到Web應用的數據,不僅僅是取得請求參數的值,往往也需要在Action里直接獲取請求或會話的一些數據,對于這些數據,現在都可以通過ActionContext來獲取到。
3:關于廣義和狹義
你會看到,在ActionContext里面其實是包含著狹義值棧的,正是因為這個原因,再加上ActionContext還包含其他的數據,因此把ActionContext稱為廣義值棧。
今后在說值棧的時候,沒有特別指明的情況下,多數就是指的廣義值棧,反正開發的時候都是說從值棧中獲取值。當然,有一種情況除外,就是在頁面上使用OGNL的時候,沒有特殊標識的情況下,默認是從value statck中取值的。
7.1.4ActionContext的基本使用
前面學習了值棧的基本知識,接下來,看看在程序中具體如何使用值棧。
1:如何獲取
要獲取ActionContext有兩個基本的方法,如果在不能獲取到ActionInvocation的地方,可以直接使用ActionContext一個靜態的getContext方法,就可以訪問到當前的ActionContext了,示例如下:
java代碼:
ActionContext?ctx?=?ActionContext.getContext();
如果在能獲取到ActionInvocation的地方,比如在攔截器里面、自定義的Result里面等,可以通過ActionInvocation來獲取到ActionContext,示例如下:
java代碼:
ActionContext?ctx?=?actionInvocation.getInvocationContext();
2:獲取過后,如何使用
ActionContext主要的功能是用來存放數據的,典型的方法如下:get(String key):根據key從ActionContext當前的存儲空間里面獲取相應的值
put(String key, Object value):把值存儲在ActionContext的存儲空間里面
Map getApplication():返回ServletContext中存儲的值
Map getSession():返回HttpSession中存儲的值
Map getContextMap():返回當前context存儲的值
Map getParameters():返回HttpServletRequest對象里面存儲的,客戶端提交的參數
ValueStack getValueStack():獲取OGNL的值棧
對于getXXX的方法,都有對應的setXXX方法,這里就不去贅述了,具體的請參看Struts2的API文檔。
3:應用示例
可以參看上一章的兩個有用的攔截器這一小節,兩個攔截器都使用了ActionContext對象,因此這里就不去贅述了。
7.1.5ValueStack的基本使用
在上一小節中,看到了ValueStack被包含在ActionContext中,ValueStack也是用來存儲對象的,但是它主要是通過OGNL表達式來訪問,也就是說,在Struts2里面主要是通過標簽來訪問的。
ValueStack有一個特點,如果訪問的值棧里有多個對象,且相同的屬性在多個對象中同時出現,則值棧會按照從棧頂到棧底的順序,尋找第一個匹配的對象。
1:如何獲取
直接由ActionContext對象的getValueStack()方法即可獲取
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對象中,并設置成為頂層對象
3:應用示例
前面的示例中,歡迎頁面顯示的帳號,是從登錄頁面填寫并傳遞到后臺的數據,假如現在想要修改在歡迎頁面顯示的帳號數據,但是前面從登錄頁面填寫并傳遞到后臺的數據不需要變化,那么該怎么實現呢?
先來分析一下,要想修改result頁面顯示的值,肯定需要在Result處理之前修改這個值,否則等Result處理完成過后再改就沒有意義了。因此,可以選用PreResultListener的技術,在里面把值修改好,然后再進行Result處理。
另外一點,在歡迎頁面是通過標簽來獲取帳號的數據并展示的,也就是說值的來源是value stack,因此,在PreResultListener里面要修改的就是value stack里面的值。
好了,清楚該干什么過后,來具體看看示例。
(1)先來實現PreResultListener,在里面修改value stack里面的值,示例如下:
java代碼:
publicclassMyPreResultimplementsPreResultListener{
publicvoidbeforeResult(ActionInvocation?actionInvocation,?String?result)?{
System.out.println("現在處理Result執行前的功能,result="+result);
actionInvocation.getInvocationContext().getValueStack().setValue("account","被修改了");
}
}
(2)實現了PreResultListener,還需要在運行之前注冊,這里選擇在Action里面來注冊這個監聽器,示例如下:
java代碼:
publicclassHelloWorldActionextendsActionSupport?{
privateString?account;
privateString?password;
privateString?submitFlag;
publicString?execute()throwsException?{
this.businessExecute();
ActionContext?c?=?ActionContext.getContext();
MyPreResult?pr?=?newMyPreResult();
c.getActionInvocation().addPreResultListener(pr);
return"toWelcome";
}
/**
*?示例方法,表示可以執行業務邏輯處理的方法,
*/
publicvoidbusinessExecute(){
System.out.println("用戶輸入的參數為==="+"account="+account+",password="+password+",submitFlag="+submitFlag);
}
//屬性對應的getter/setter方法,省略了
}
(3)相應的struts.xml就比較簡單了,示例如下:
java代碼:
/s2impl/welcome.jsp
(4)登錄頁面沒有變動,示例如下:
java代碼:
賬號:
密碼:
(5)再看看歡迎頁面,也沒有變動,示例如下:
java代碼:
歡迎賬號為的朋友來訪
(6)去運行測試看看,歡迎頁面顯示出來的就應該是修改過后的值了,如下圖所示:
圖7.1? 修改result數據的歡迎頁面
由于通常情況下,向value stack里面壓入值都是由Struts2去完成,而訪問value stack多是通過標簽中的OGNL表達式,因而直接使用ValueStack的機會并不是很多。
總結
以上是生活随笔為你收集整理的java值栈_Struts2 中的值栈是什么?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 简述oracle数据库特殊状态,【Ora
- 下一篇: mysql入门到跑路_Mysql入门二十