struts2--關於值棧的概念性問題

重要參考:http://www.cnblogs.com/ningvsban/p/3739622.html

http://www.cnblogs.com/ningvsban/p/3739682.html

結論:

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來獲取到。

關於廣義值棧和狹義值棧

你會看到,在ActionContext裏面其實是包含着狹義值棧的,正是因爲這個原因,再加上ActionContext還包含其他的數據,因此把ActionContext稱爲廣義值棧。今後在說值棧的時候,沒有特別指明的情況下,多數就是指的廣義值棧,反正開發的時候都是說從值棧中獲取值。當然,有一種情況除外,就是在頁面上使用OGNL的時候,沒有特殊標識的情況下,默認是從value statck中取值的。

值棧其實就是內存分析,在Struts2中就叫根對象和棧文本,類似於JAVA中對變量和對象的內存分析


值棧ValueStack是Struts2框架核心組件,它提供對上下文信息和執行環境中元
素的訪問機制。其在底層實現了一個棧
值棧由以下4個層級對象組成
(1)臨時對象:這些對象在請求處理過程中需要臨時保存,比如集合中當前正在迭代的元素;
(2)
(2) 模型對象:當Action實現了ModelDriven接口時,模型對象就會被存放在棧中被執行的Action前面;否則不存在這個級別的內容。
(3) Action對象:此對象爲當前正在執行的action。
(4) 命名對象:任何對象都可以被賦予一個標誌符而成爲命名對象。比如與HTTP同等作用域的對象集合對應的Struts2命名對象,#application、#session、#request、#attr和#parameters等。

當struts2框架接收到一個HTTP請求時,它立刻創建一個ActionContext、ValueStack、Action對象 , 然後把action對象存放進ValueStack 中,再通過ActionContext 對象訪問ValueStack 中的信息,而這個訪問的過程就是OGNL表達式訪問操作

值棧中分爲root根對象和棧文本,值棧中主要存放Action對象,棧文本里主要是一些Map映射parameters、request、session、application、attr

Ø在action中訪問值棧
每個請求都建立一個與相應Action對應的ActionContext作爲OGNL的上下文環境和ValueStack,並且把Action裏面的屬性值壓入ValueStack,這時的屬性值都是初始化值
從ActionContext 中獲取上下文對象
ActionContext actionContext=ActionContext.getContext();
再從上下文對象中獲取值棧
ValueStack valueStack=actionContext.getValueStack();

Ø操作根對象中的數據
從值棧中獲取指定位置的根對象
valueStack.getRoot().get(0);
這個對象可以是當前的action對象,然後就可以操作當前對象中的數據了
它還提供了更加方便的取值方法,直接就從根對象中取值
valueStack.findValue(“…");
給根對象中的屬性設置值,如果屬性名稱一樣,會覆蓋之前的屬性值
valueStack.setValue(“…");//要求action中有set方法,即給屬性重新賦值
valueStack.set(“…”);//隨意一個屬性名稱,在根對象中會生成一個HashMap,(在後臺調試中可以看到),不需要set方法,就是一個獨立的屬性(最新版本一樣)
還可以往值棧中壓對象,把對象壓力棧頂
valueStack.getRoot().push(“…");

Ø操作棧文本中的數據
因爲棧文本中主要存放parameters、request、session、application、attr的Map映射,以便在頁面上直接可以訪問。其實這個棧文本就是爲了封裝servlet中的request、session等對象,實現松耦合,以後對request等對象的參數或屬性的操作就可以用requestMap的屬性操作
獲取requestMap
requestMap=(Map)ActionContext.getContext().get("request");
然後通過requestMap的key(參數或者屬性) requestMap.get(“key”),就能獲取參數或者屬性的值了
因爲當一個請求過來,ActionContext就能接受所有的請求參數,並且存放在ActionContext 棧文本中,可以獲取對應的棧文本或者對其進行修改
給requestMap賦值,其實底層就是在給request對象賦值
(Map)ActionContext.getContext().get("request"). put(“”,””);

Ø在頁面中訪問值棧
在Struts2頁面中操作值棧,OGNL表達式需要配合Struts標籤纔可以使用
如:<s:property value="name"/>
爲了方便在頁面端測試,打開<s:debug></s:debug>標籤

一個OGNL表達式,必須選擇ActionContext中的一個對象作爲根對象(root),默認情況下,是選擇valueStack作爲根對象,如果需要使用另外5個對象作爲根對象,需要加上#前綴 

簡練總結:

廣義值棧包括臨時變量、狹義值棧(value stack,默認狹義value stack爲根對象,是一個意思,尤其在OGNL表達式中),還有application session request attr parameters(都在棧文本中) 這三類,重要的是在狹義值棧中,也就是默認的根對象中(可以指定棧文本爲根對象),這裏主要存放着action對象,以及action對象的一些屬性變量(可以直接通過狹義值棧跳過根目錄直接對根目錄中的變量取值)

獲得上下文對象(廣義值棧)

ActionContext.getContext();

獲得狹義值棧的方法

ActionContext.getContext().getValueStack();

獲得狹義值棧中的根對象的方法(默認狹義值棧中的爲根對象)
ActionContext.getContext().getValueStack().getRoot();
獲取指定位置的根對象
ActionContext.getContext().getValueStack().getRoot().get(0);
直接通過狹義值棧跳過根目錄直接對根目錄中的變量取值
ActionContext.getContext().getValueStack().findValue(“…");
給根對象中的屬性設置值,如果屬性名稱一樣,會覆蓋之前的屬性值
valueStack.setValue(“…");//要求action中有set方法,即給屬性重新賦值
valueStack.set(“…”);//隨意一個屬性名稱,在根對象中會生成一個HashMap,(在後臺調試中可以看到),不需要set方法,就是一個獨立的屬性(最新版本一樣)
還可以往值棧中壓對象,把對象壓力棧頂
valueStack.getRoot().push(“…");

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章