之前用ssh框架,在action中总是将查询出的数据存到session或者request中,然后传到前台进行显示;但后来我看到有些代码 在action中声明一个list或者其他的成员变量,然后将查询到的数据赋给这个成员变量,然后再jsp页面通过${list}或者 ${变量名} 就可以在前台显示了。之前一直不明白,经过查阅资料,这样做可行的原因:
用JSTL的${tip}可以访问Action中定义tip属性:private String tip,
${tip}实际上是访问的request作用域中的tip,实际是调用了action中的getTip()方法,所以能访问。
然后Struts2是把值栈保存在 request 中的。你可以通过 request.getAttribute( "struts.valueStack" ); 得到它。
经过我的分析研究,结论如下:其实数据是被存放在requestContext中的,而request对象及其session等对象又被放入了ActionContext中,通过ognl表达式是从ActionContext中获取requestContext里面存放的对象,而用jstl是直接从request中获取对象
即:用jstl是直接获取,而用ognl是间接的从ActionContext中获取request对象中的数据
ActionContext的解释如下:ActionContext中包含了大量的环境信息,包括:Locale、Application、Session、ValueStack等等。
查看该类源码,发现它装饰了getAttribute()方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public
Object getAttribute(String s) {
if
(s !=
null
&& s.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(s);
}
ActionContext ctx = ActionContext.getContext();
Object attribute =
super
.getAttribute(s);
boolean
alreadyIn =
false
;
Boolean b = (Boolean) ctx.get(
"__requestWrapper.getAttribute"
);
if
(b !=
null
) {
alreadyIn = b.booleanValue();
}
// note: we don't let # come through or else a request for
// #attr.foo or #request.foo could cause an endless loop
if
(!alreadyIn && attribute ==
null
&& s.indexOf(
"#"
) == -
1
) {
try
{
// If not found, then try the ValueStack
ctx.put(
"__requestWrapper.getAttribute"
, Boolean.TRUE);
ValueStack stack = ctx.getValueStack();
if
(stack !=
null
) {
attribute = stack.findValue(s);
}
}
finally
{
ctx.put(
"__requestWrapper.getAttribute"
, Boolean.FALSE);
}
}
|
结论:
EL能访问到值栈中的内容。
之所以能访问到,是因为EL可以访问request的getAttribute()方法,而此方法被Sturts2进行了装饰,可以访问到ActionContext,进而可以访问到值栈。
总结一下:
为什么JSTL可以访问Action中的属性,如:
private String tip;
public String getTip(){
return this.tip;
}
在JSP页面中可用${tip}访问到tip属性。
总结一下答案:
①JSTL能访问Action中通过request.setAttribute("")设置的值。这是大家所熟悉的。
②JSTL能访问Action中属性(通过getXXX方法实现访问)。
因为ValueStack存在于request,所以用${tip}访问时的顺序是:request先访问ValueStack,ValueStack从中找出tip对应的值。