此文整理自论坛的一个讨论帖子,我已经加精
其中 35楼的huangwen9 以及 37 楼的huangpeihp 给出了正确的解释。
原帖子在这里:http://topic.csdn.net/u/20080410/16/59a5734b-d4b5-490d-a4ab-9f63dc7a2708.html
系统现象
1 测试的Bean为
package
net.java2000.html;
public
class
CounterBean
...
{
private int count = 0;
public CounterBean() ...{
}
public int getCount() ...{
return count;
}
public void setCount(int count) ...{
this.count = count;
}
}
<
jsp:useBean id
=
"
myBean
"
scope
=
"
session
"
class
=
"
net.java2000.html.CounterBean
"
/>
<
jsp:getProperty name
=
"
myBean
"
property
=
"
count
"
/>
<
br
>
<%=
myBean.getCount()
%>
<
jsp:setProperty name
=
"
myBean
"
property
=
"
count
"
value
=
"
<%=myBean.getCount()+1%>
"
/>
0
0
刷新后为
1
1
刷新后为
2
2
刷新后为
3
3
4 OK,如果我们现在把jsp文件里面的 session 改成 application
<
jsp:useBean id
=
"
myBean
"
scope
=
"
application
"
class
=
"
net.java2000.html.CounterBean
"
/>
<
jsp:getProperty name
=
"
myBean
"
property
=
"
count
"
/>
<
br
>
<%=
myBean.getCount()
%>
<
jsp:setProperty name
=
"
myBean
"
property
=
"
count
"
value
=
"
<%=myBean.getCount()+1%>
"
/>
5 运行结果为
第一次刷新
4
0
第二次刷新
1
0
第三次刷新
1
0
以后无论如何刷新,都是着个数字
难道是jsp的bug?
系统分析
1 我们先查看一下生成的源代码
synchronized (application) ... {
// #######注意这里 1 ############
myBean = (net.java2000.html.CounterBean) _jspx_page_context.getAttribute("myBean", PageContext.APPLICATION_SCOPE);
if (myBean == null)...{
myBean = new net.java2000.html.CounterBean();
_jspx_page_context.setAttribute("myBean", myBean, PageContext.APPLICATION_SCOPE);
}
}
out.write( ' ' );
out.write( ' ' );
// #######注意这里 2 ############
out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString((((net.java2000.html.CounterBean)_jspx_page_context.findAttribute( " myBean " )).getCount())));
out.write( " " );
out.write( "
" );
// #######注意这里 3 ############
out.print(myBean.getCount());
out.write( ' ' );
out.write( ' ' );
// #######注意这里 4 ############
org.apache.jasper.runtime.JspRuntimeLibrary.handleSetProperty(_jspx_page_context.findAttribute( " myBean " ), " count " ,
myBean.getCount() + 1 );
2 我们来看一下那个 findAttribute方法的说明
* Searches for the named attribute in page, request, session (if valid),
* and application scope(s) in order and returns the value associated or
* null.
*
* @param name the name of the attribute to search for
* @return the value associated or null
* @throws NullPointerException if the name is null
*/
abstract public Object findAttribute(String name);
3 问题就在于那个 findAttribute
是按照顺序从 page, request, session (if valid),和 application 顺序查找的,如果在前一个找到,则会返回。
1)我们的程序一开始为session,所以数字很规律的从0涨到了3,此时session里面的数字为4
2)当我们修改application时,此时myBean变成了一个新的对象,并保存在PageContext.APPLICATION_SCOPE中,其数值为0
3)当运行到 #2 的输出时,由于session并没有失效,其findAttribute会优先查到session里面同名的myBean,所以输出了那个4
4)#3 输出的是我们新建的对象,所谓数字为0
5)#4 的地方是有点奇怪的,他把我们新建的myBean对象的数值+1, 然后保存到了 session 的 myBean 里面,数字为0+1 = 1;
4 再次刷新
1) #1 没啥特殊的,拿到了那个为0的对象
2) #2 由于上一次刷新,所以数值为1
3) $3 依然是0
4) 再一次重复了前一次刷新的步骤, 0+1=1 然后保存到了session里面
总结:
由于findAttriute的特殊性,所以在使用的时候要注意,必要时重启容器是一个很简单,但有效的解决方法。
就如同操作系统有问题,解决不了,干错重启机器是一样的。呵呵!
延伸:
如果一开始为 application, 刷新4次后,改成session会怎样么??