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.
void
push(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";
}
}