Struts2中的值棧

來源:互聯網
上載者:User
一、值棧是什麼

        簡單的說:值棧是對應每一個請求對象的輕量級的記憶體資料中心。

        Struts2中一個很激動人心的特性就是引入了值棧,在這裡統一管理著資料,供Action、Result、Interceptor等Struts2的其他部分使用,這樣一來,資料被集中管理起來而不會淩亂,大大方便了程式編寫。

        Struts2中關於值棧的另外一個很激動人心的特性就是:大多數情況下,你根本無需關心值棧,你不用管它在哪裡,不用管它裡面有什麼,你只需要去擷取自己需要的資料就可以了。也就是說,你可以隱式的使用值棧。

        當然,如果編寫自訂的Result或攔截器等較複雜功能的時候,還是需要顯示訪問值棧的,因此,還是需要你掌握值棧的知識。

二、值棧能幹什麼

        簡單的說,值棧能夠安全執行緒的為每個請求提供公用的資料存取服務。

        當有請求到達的時候,Struts2會為每個請求建立一個新的值棧,也就是說,值棧和請求是一一對應的,不同的請求,值棧也不一樣,而值棧封裝了一次請求所有需要操作的相關的資料。

        正是因為值棧和請求的對應關係,因而值棧能保證安全執行緒的為每個請求提供公用的資料存取服務。

三、值棧有什麼

          事實上,到現在為止,我們一直在講“值棧”,這種說法其實是不夠準確的。為什麼呢。因為在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中取值的。

四、  ActionContext的基本使用


前面學習了值棧的基本知識,接下來,看看在程式中具體如何使用值棧。

1:如何擷取

要擷取ActionContext有兩個基本的方法,如果在不能擷取到ActionInvocation的地方,可以直接使用ActionContext一個靜態getContext方法,就可以訪問到當前的ActionContext了,樣本如下:

ActionContext ctx = ActionContext.getContext();  
如果在能擷取到ActionInvocation的地方,比如在攔截器裡面、自訂的Result裡面等,可以通過ActionInvocation來擷取到ActionContext,樣本如下:

ActionContext ctx = actionInvocation.getInvocationContext();  

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文檔。 五、ValueStack的基本使用

在上一小節中,看到了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裡面的值,樣本如下:

public class MyPreResult implements PreResultListener{  02.    public void beforeResult(ActionInvocation actionInvocation, String result) {  03.        System.out.println("現在處理Result執行前的功能,result="+result);  04.        actionInvocation.getInvocationContext().getValueStack().setValue("account", "被修改了");  05.    }  06.}  
(2)實現了PreResultListener,還需要在運行之前註冊,這裡選擇在Action裡面來註冊這個監聽器,樣本如下:

public class HelloWorldAction extends ActionSupport {  02.    private String account;  03.    private String password;  04.    private String submitFlag;  05.    public String execute() throws Exception {  06.        this.businessExecute();  07.        ActionContext c = ActionContext.getContext();  08.        MyPreResult pr = new MyPreResult();  09.        c.getActionInvocation().addPreResultListener(pr);  10.        return "toWelcome";  11.    }  12.    /** 13.     * 樣本方法,表示可以執行商務邏輯處理的方法, 14.     */  15.    public void businessExecute(){  16.        System.out.println("使用者輸入的參數為==="+"account="+account+",password="+password+",submitFlag="+submitFlag);  17.    }  18.    //屬性對應的getter/setter方法,省略了  19.}  

(3)相應的struts.xml就比較簡單了,樣本如下:

01.<package name="helloworld"  extends="struts-default">  02.        <action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">  03.            <result name="toWelcome">/s2impl/welcome.jsp</result>  04.        </action>  05.    </package>  

(4)登入頁面沒有變動,樣本如下:

01.<form action="/helloworld/helloworldAction.action" method="post">  02.    <input type="hidden" name="submitFlag" value="login"/>  03.    帳號:<input type="text" name="account"><br>  04.    密碼:<input type="password" name="password"><br>  05.    <input type="submit" value="提交">  06.</form>  
(5)再看看歡迎頁面,也沒有變動,樣本如下:

<%@ taglib prefix="s" uri="/struts-tags"%>  02.歡迎帳號為<s:property value="account"/>的朋友來訪  
(6)去運行測試看看,歡迎頁面顯示出來的就應該是修改過後的值了,如下圖所示:



      由於通常情況下,向value stack裡面壓入值都是由Struts2去完成,而訪問value stack多是通過標籤中的OGNL運算式,因而直接使用ValueStack的機會並不是很多。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.