1、问题

提交页面:

	<h4>注册产品</h4>
<form action="save.do" method="post">
pName:<input type="text" name="pName" /><br />
pDesc:<input type="text" name="pDesc" /><br />
pPrice:<input type="text" name="pPrice" /><br />
<input type="submit" value="submit" />
</form>

响应页面:

	<h4>详细信息</h4>
Name:${pName}<br/><br/>
Desc:${pDesc}<br/><br/>
Price:${pPrice}<br/><br/>

${pName},${pDesc},${pPrice},写法简单优雅,优雅的背后肯定有故事,struts2在背后帮我们做了些什么?

2、StrutsRequestWrapper

(1)打印出request看看

request:<%=request %>
request:org.apache.struts2.dispatcher.StrutsRequestWrapper@37c4d046

(2)StrutsRequestWrapper源码

package org.apache.struts2.dispatcher;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper; import static org.apache.commons.lang3.BooleanUtils.isTrue; public class StrutsRequestWrapper extends HttpServletRequestWrapper { private static final String REQUEST_WRAPPER_GET_ATTRIBUTE = "__requestWrapper.getAttribute";
private final boolean disableRequestAttributeValueStackLookup; /**
* The constructor
* @param req The request
*/
public StrutsRequestWrapper(HttpServletRequest req) {
this(req, false);
} /**
* The constructor
* @param req The request
* @param disableRequestAttributeValueStackLookup flag for disabling request attribute value stack lookup (JSTL accessibility)
*/
public StrutsRequestWrapper(HttpServletRequest req, boolean disableRequestAttributeValueStackLookup) {
super(req);
this.disableRequestAttributeValueStackLookup = 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;
}
}

  从代码中可以看出,StrutsRequestWrapper重写了getAttribute,其中有一段核心代码如下:

                    ValueStack stack = ctx.getValueStack();
if (stack != null) {
attribute = stack.findValue(key);
}

  debug代码,可以看出${pName}等是从ValueStack中获取出来的

3、ValueStack

  首先这是一个接口,里面有两个关键声明方法

public abstract Map<String, Object> getContext();

public abstract CompoundRoot getRoot();

  debug代码,可以发现ValueStack包括两个核心属性

struts2笔记10-值栈-LMLPHP

一个context,一个root,context里面包含的是一系列map,requestMap,applicationMap,sessionMap等;

root是一个CompoundRoot对象,其实也是个map,这里面包括的就是我们自己Action对象了

struts2笔记10-值栈-LMLPHP

${pName}等正是从这里查出来的,并非从request中获取的。

 

04-27 23:29