(14)Struts2_值棧

Struts2_值棧

借用在前面演示 hello world 的時候的例子。

在show.jsp 頁面那些字段的值到底是怎麼取得呢?現在在show.jsp中輸出request

<%@ page language="java" import="java.util.*" pageEncoding="utf-8" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>
  <body>
       ID:${id}<br>
       編號:${ dlh}<br>
       姓名:${ name}<br>
       部門:${ bmmc}<br>
      <%=request %>
  </body>
</html>

可見,request是經過Struts包裝過後的。

ctrl+shift+t 查看StrutsRequestWrapper類的 源碼

public class StrutsRequestWrapper extends HttpServletRequestWrapper {

    private static final String REQUEST_WRAPPER_GET_ATTRIBUTE = "__requestWrapper.getAttribute";
    private final boolean disableRequestAttributeValueStackLookup;

    ......

    /**
     * Gets the object, looking in the value stack if not found
     *
     * @param key The attribute key
     */
    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);
                }
            }
        }
        return attribute;
    }
}

當從super.getAttribute(key)獲取不到值時,會從ValueStack中去取,super即HttpServletRequestWrapper 。所以,頁面輸出的值是從值棧裏面取到的值,而並非是request請求域中有這麼一些屬性值。

debug斷點調式

ActionContext其實是對OgnlContext的包裝。

root即爲實際意義上的後進先出的一個棧;值棧在頁面取值輸出的時候,就是從root屬性裏取其所含的對象的屬性的值。

其中root屬性爲CompoundRoot對象,查看其源碼可知。

public class CompoundRoot extends CopyOnWriteArrayList<Object> {

    private static final long serialVersionUID = 8563229069192473995L;

    public CompoundRoot() {
    }

    public CompoundRoot(List<?> list) {
        super(list);
    }


    public CompoundRoot cutStack(int index) {
        return new CompoundRoot(subList(index, size()));
    }

    public Object peek() {
        return get(0);
    }

    public Object pop() {
        return remove(0);
    }

    public void push(Object o) {
        add(0, o);
    }
}

其繼承了list,進棧push添加到第一個,其前的往後移;出棧刪除第一個,其後的往前移。


總結:

ValueStack(值棧):

I. 可以從 ActionContext 中獲取值棧對象

II. 值棧分爲兩個邏輯部分

  • Map 棧: 實際上是 OgnlContext 類型, 是個 Map, 也是對 ActionContext 的一個引用. 裏邊保存着各種 Map: requestMap, sessionMap, applicationMap, parametersMap, attr
  • 對象棧: 實際上是 CompoundRoot 類型, 是一個使用 ArrayList 定義的棧. 裏邊保存各種和當前 Action 實例相關的對象.是一個數據結構意義的棧.

貫穿整個 Action 的生命週期(每個 Action 類的對象實例都擁有一個 ValueStack 對象). 相當於一個數據的中轉站. 在其中保存當前 Action 對象和其他相關對象.

Struts 框架把 ValueStack 對象保存在名爲 “struts.valueStack” 的請求屬性中


在 ValueStack 對象的內部有兩個邏輯部分:

  • ObjectStack: Struts 把 Action 和相關對象壓入 ObjectStack 中
  • ContextMap: Struts 把各種各樣的映射關係(一些 Map 類型的對象) 壓入 ContextMap 中. 實際上就是對 ActionContext 的一個引用

Struts 會把下面這些映射壓入 ContextMap 中

  • parameters: 該 Map 中包含當前請求的請求參數
  • request: 該 Map 中包含當前 request 對象中的所有屬性
  • session: 該 Map 中包含當前 session 對象中的所有屬性
  • application:該 Map 中包含當前 application 對象中的所有屬性
  • attr: 該 Map 按如下順序來檢索某個屬性: request, session, application
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章