JSP使用get/setProperty时,Bean的scope 改变引起的问题

系统现象
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;
  }
}2 测试的 JSP 为


<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%>" />
3 运行结果为
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 运行结果为
第一次刷新


第二次刷新


第三次刷新

以后无论如何刷新,都是着个数字

难道是jsp的bug?


系统分析
1 我们先查看一下生成的源代码

 

 

      net.java2000.html.CounterBean myBean = null;
      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会怎样么??

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值