1. 程式人生 > >Struts2值棧學習

Struts2值棧學習

1:簡單的說,值棧是對應每一個請求物件的輕量級的資料儲存中心,在這裡統一管理著資料,供Action、Result、Interceptor等Struts2的其他部分使用,這樣資料被集中管理起來而不凌亂。

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

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

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

2:狹義值棧

     通常是指com.opensymphony.xwork2.util.ValueStack介面的物件,目前就是com.opensymphony.xwork2.ognl.OgnlValueStack物件。

     狹義值棧主要用來存放動態EL(表示式語言)運算需要的值和結果,當然OgnlValueStack物件主要是用來支援OGNL(物件圖導航語言)運算的。

     狹義值棧中存放著一些OGNL可以訪問的資料,如下:

        a:action的例項,這樣就可以通過OGNL來訪問Action例項中的屬性的值了。

        b:OGNL表示式運算的值,可以設定到值棧中,可以主動訪問值棧物件,強行設定。

        c:OGNL表示式產生的中間變數,比如使用Struts2標籤的時候,使用迴圈標籤,自然會有迴圈的變數,這些都放在值棧中。

3:廣義值棧

   通常是ActionContext物件,ActionContext是Action執行的上下文,每個ActionContext是一個基本的容器,包含著Aciton執行需要的資料,比如請求引數,會話等。

  ActionContext也是執行緒安全的,每個執行緒都有一個獨立的ActionContext,這樣就不用擔心值棧中值得執行緒安全問題了。

  ActionContext裡面儲存著很多值,如下:

     a:Request的Parameters,請求中的引數,注意這裡的資料是從資料物件中複製來的,因此這裡的資料的變化是不會影響到請求物件裡面的引數的值的。

     b:Request的Attribute,請求中的屬性,這裡是一個Map,存放著請求物件的屬性資料,這些資料和請求物件的Attribute是聯動的。

     c:Application的Attribute,應用的屬性,這裡是一個Map,存放著應用物件的屬性資料,這些資料和應用物件的attribute是聯動的。

     d:ValueStack,也就是狹義值棧,ActionContext是以value stack作為被OGNL訪問的根,簡單的說,OGNL在沒有特別指明的情況下,訪問的就是value stack的值。

     e:attr,在所有的屬性範圍中獲取值,依次搜尋page, request, session 和applicaion

4:ActionContext的使用

   獲取,通過兩種方式,第一種,使用ActionContext自身的方法來獲取

     ActionContext ctx = ActionContext.getContext();

   第二種,使用ActionInvocation來獲取

     ActionContext ctx = actionInvocation.getInvocationContext();

   它的典型方法如下:

    get(String key):Returns a value that is stored in the current ActionContext by doing a lookup using the value's key.

  void put(String key,Object value):Stores a value in the current ActionContext.

  ():  Returns a Map of the ServletContext when in a servlet environment or a generic application level Map otherwise.

                                         即返回ServletContext中返回的值

():Gets the Map of HttpSession values when in a servlet environment or a generic session map otherwise.

  (): Returns a Map of the HttpServletRequest parameters when in a servlet environment or a generic Map of parameters otherwise.

5:ValueStack的使用

   ValueStack有一個特點,如果訪問的值棧裡有多個物件,且相同的屬性在多個物件中同時出現,則值棧會按照從棧頂到棧底的順序,尋找第一個匹配的物件。

   ValueStack的獲取:直接由ActionContext物件的getValueStack()方法即可獲得。

   使用函式:

   (String expr): Find a value by evaluating the given expression against the stack in the default search order.

    void(String expr,Object value):  Attempts to set a property on a bean in the stack with the given expression using the default search order.

    peek():Get the object on the top of the stack without changing the stack.

     pop():Get the object on the top of the stack and remove it from the stack.

     voidpush(Object o):Put this object onto the top of the stack

6:例子,修改使用者輸入的引數資訊,如下圖所示,


      圖:使用者輸入了aa的username


                   圖:使用者提交後發現username屬性的值發生了變化

實現:

  首先定義一個實現PreResultListener介面的類:MyPreResultListener

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.PreResultListener;

public class MyPreResultListener implements PreResultListener {

	@Override
	public void beforeResult(ActionInvocation invocation, String resultCode) {
		System.out.println("現在處理Result執行前的功能, result=" + resultCode);
		
		//在Result處理之前修改value stack裡面的username對應的值
	    invocation.getInvocationContext().getValueStack().setValue("username", "被修改了");

	}

}

然後在相應的Action中進行註冊:

import com.capinfotech.listener.MyPreResultListener;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class PreResultAction extends ActionSupport {

	private String username;
	private String password;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
	
	public String execute() {
		System.out.println("使用者輸入的引數為,username:" + username + ", password:" + password);
		
		ActionContext context = ActionContext.getContext();
		MyPreResultListener preListener = new MyPreResultListener();
		context.getActionInvocation().addPreResultListener(preListener);
		
		return "success";
		
	}

}