struts2笔记10-值栈
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包括两个核心属性
一个context,一个root,context里面包含的是一系列map,requestMap,applicationMap,sessionMap等;
root是一个CompoundRoot对象,其实也是个map,这里面包括的就是我们自己Action对象了
${pName}等正是从这里查出来的,并非从request中获取的。