1、什麼是值棧
ValueStack是Struts2的接口,OGNLValueStack是該接口的實現類。ValueStack相當於Struts2數據的中轉站,ValueStack貫穿了整個Action的生命週期,Action是多例的,一次服務器請求就會創建一個Action的實例,同時會爲這個Action創建一個ValueStack對象。Struts2通過OGNL表達式獲取值棧的數據。
2、值棧的內部結構
3、ActionContext與值棧的關係
ActionContext:Action的上下文。通過源碼查看:Struts的核心過濾器執行的過程中,創建ActionContext對象,在創建ActionContext對象的同時創建一個ValueStack,並且將ValueStack存入到ActionContext中。所以通過ActionContext對象,獲得值棧。其實在ValueStack的內部有一個ActionContext的引用。
public class A{
private B b;
}
public class B{
private A a;
}
ActionContext中有ValueStack的引用,ValueStack中也有ActionContext的引用。
ActionContext之所以能夠訪問Servlet的API其實也是依賴了值棧的。
4、如何獲取值棧
- 通過ActionContext獲取
ValueStack valueStack1 = ActionContext.getContext().getValueStack();
- 通過request對象獲取-因爲執行Action的過程中,將值棧存入到request域中。
// 獲得reqeust對象獲取
ValueStack valueStack2 = (ValueStack) ServletActionContext.getRequest()
.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
5、如何操作值棧(操作root區域)
- 直接操作值棧對象
* void set(String name,Object value);
* void push(Object obj);
- 直接在Action對象提供成員屬性
當Action的實例被創建了,默認的情況下(沒有手動操作值棧,沒有實現模型驅動),Action對象在棧頂的位置。Action中的屬性也會在棧中。提供一個屬性,對該屬性提供一個get方法就可以了。
6、獲取值棧的數據
- 在頁面中使用OGNL表達式進行獲取
<h3>獲取值棧的root區數據</h3>
<s:property value="name"/><br/>
<s:property value="user.username"/>
<s:property value="user.password"/><br/>
<s:property value="username"/>
<s:property value="password"/><br/>
<s:property value="list[0].username"/>
<s:property value="list[0].password"/>
<s:property value="list[1].username"/>
<s:property value="list[1].password"/>
<h3>獲取值棧的context區數據</h3>
<s:property value="#request.name"/>
<s:property value="#session.name"/>
<s:property value="#application.name"/>
<s:property value="#attr.name"/>
<s:property value="#parameters.id"/>
7、EL如何訪問值棧
public Object getAttribute(String key) {
if (key == null) {
throw new NullPointerException("You must specify a key value");
}
if (disableRequestAttributeValueStackLookup || key.startsWith("javax.servlet")) {
// don't bother with the standard javax.servlet attributes, we can short-circuit this
// see WW-953 and the forums post linked in that issue for more info
return super.getAttribute(key);
}
ActionContext ctx = ActionContext.getContext();
Object attribute = super.getAttribute(key);
if (ctx != null && attribute == null) {
boolean alreadyIn = isTrue((Boolean) ctx.get(REQUEST_WRAPPER_GET_ATTRIBUTE));
// note: we don't let # come through or else a request for
// #attr.foo or #request.foo could cause an endless loop
if (!alreadyIn && !key.contains("#")) {
try {
// If not found, then try the ValueStack
ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.TRUE);
ValueStack stack = ctx.getValueStack();
if (stack != null) {
attribute = stack.findValue(key);
}
} finally {
ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.FALSE);
}
}
}
returnattribute;
}