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;
public class StrutsRequestWrapper extends HttpServletRequestWrapper
{
public StrutsRequestWrapper(HttpServletRequest req)
{
super(req);
}
public Object getAttribute(String s)
{
if ((s != null) && (s.startsWith("javax.servlet")))
{
return super.getAttribute(s);
}
ActionContext ctx = ActionContext.getContext();
Object attribute = super.getAttribute(s);
if ((ctx != null) &&
(attribute == null)) {
boolean alreadyIn = false;
Boolean b = (Boolean)ctx.get("__requestWrapper.getAttribute");
if (b != null) {
alreadyIn = b.booleanValue();
}
if ((!alreadyIn) && (s.indexOf("#") == -1)) {
try
{
ctx.put("__requestWrapper.getAttribute", Boolean.TRUE);
ValueStack stack = ctx.getValueStack();
if (stack != null)
attribute = stack.findValue(s);
}
finally {
ctx.put("__requestWrapper.getAttribute", Boolean.FALSE);
}
}
}
return attribute;
}
}
这是struts2中StrutsRequestWrapper的源码
从 ((!alreadyIn) && (s.indexOf("#") == -1)
可以看出 如果ognl表达式中没有加"#" 如果在 parameter,request,session,application,attr 中没有找到对应的“属性”则会继续到ValueStack(root)中找。相反如果加了"#"则不会在ValueStack寻找。
比如:${#requestScope.name} 如果在request中没找到name则停止寻找,直接返回。
${requestScope.name} 如果在request中没找到name则会继续在ValueStatck中继续寻找。
补充:
OGNL是一个对象,属性的查询语言。在OGNL中有一个类型是Map的Context(称为上下文),在这个上下文中有一个跟元素(root),对跟元素的属性的访问可以直接使用属性名字,但是对于其他非跟元素的访问必须加上特殊符号#。
在Struts2中 上下文为ActionContext,根元素位Value Stack(值堆栈,值堆栈代表了一族对象而不是一个对象,其中Action类的实
例也属于值堆栈的一个)。ActionContext中的内容如下图:
|
|--application
|
|--session
context map---|
|--value stack(root)
|
|--request
|
|--parameters
|
|--attr (searches page, request, session, then application scopes)
|
因为Action实例被放在Value Stack中,而Value Stack又是根元素(root)中的一个,所以对Action中的属性的访问可以不使用标记#,而对其他的访问都必须使用#标记。
在JSP2.1中#被用作了JSP EL(表达式语言)的特殊记好,所以对OGNL的使用可能导致问题,
一个简单的方法是禁用JSP2.1的EL特性,这需要修改web.xml文 件:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>true</el-ignored>
</jsp-property-group>
</jsp-config>