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

本文探讨了JSP中使用不同作用域(session与application)时出现的计数器行为异常现象,通过分析自动生成的源代码及findAttribute方法的工作原理,揭示了导致该现象的原因,并提出了解决方案。

此文整理自论坛的一个讨论帖子,我已经加精

其中 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; 
  }
 
}
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会怎样么??

代码下载链接: https://pan.quark.cn/s/a175d1ef418b 标题部分中的"新建文件夹 (2).zip"暗示这是一个采用ZIP编码方式的压缩文档,这种格式通常用于将多个关联的文件或目录整合进一个压缩单元中。在信息技术领域,ZIP编码格式是一种广泛应用的标准,它支持将多个数据单元压缩成一个独立的压缩文件,从而提升文件传输的便捷性、存储空间的利用效率以及管理的便捷度。ZIP格式的压缩文件可以通过多种解压缩工具进行访问,例如WinRAR软件、7-Zip应用程序或操作系统自带的压缩解压功能。 描述文本里的"shop"字样或许指向这个压缩文档与商业店铺、电子商务平台或网络销售系统存在关联。在Java编程范畴内,这有可能是一个范例项目,用以说明构建电子商务平台相关功能的实现方法,涵盖商品维护、购物车功能以及订单处理等模块。Java语言因其跨平台兼容性、系统稳定性以及完备的库资源支持,经常被选作开发大型企业级应用的技术栈,尤其是电子商务系统。 依据标签"java"的指示,可以推断压缩包内部可能包含了采用Java编程语言编写的源代码片段、系统配置文档、数据库操作脚本及其他辅助性资源。Java程序员一般借助集成开发环境(IDE)如Eclipse、IntelliJ IDEA或NetBeans进行Java代码的编写、编译及执行操作。这些开发工具能够高效地支持ZIP文件中项目结构的导入与管理。 文件命名列表仅列出一个条目"新建文件夹 (2)",这或许意味着压缩文档中包含一个同名的文件夹,该文件夹内可能收纳了一系列子文件及子目录。在实际的Java开发任务中,类似的结构可能包含src目录(存放程序源代码)、lib目录(存放项目依赖的jar库文件)、resou...
内容概要:本文系统研究了基于Kantorovich距离的SBR(Sequential Benefit Replacement)算法在电力系统场景削减中的应用,旨在从大量原始不确定性场景中筛选出最具代表性的典型场景,以降低随机优化问题的计算复杂度。该方法通过引入Kantorovich距离(也称Wasserstein距离)精确量化场景之间的差异性,并结合SBR算法实现场景的逐步合并与削减,有效保留原始场景的概率分布特征。文中提供了完整的Matlab代码实现,便于用户复现算法,特别适用于处理风电出力、负荷波动等具有强随机性和不确定性的多场景优化问题,如微电网调度、电氢耦合系统运行等。; 适合人群:具备一定概率统计、优化理论基础和Matlab编程能力,从事电力系统、新能源并网、能源互联网、随机规划及综合能源系统优化等领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于高比例可再生能源接入下的电力系统随机优化调度、微电网能量管理、多能互补系统等需要进行多场景分析与决策的建模场景;②帮助研究人员深入掌握Kantorovich距离的数学原理与计算方法,以及SBR算法的迭代逻辑与实现技巧,提升对不确定性建模、场景生成与削减技术的理解与应用能力; 阅读建议:建议读者结合提供的Matlab代码,重点理解距离矩阵的构建、场景权重的更新规则以及场景合并的判定逻辑,通过调试代码并代入实际风电或负荷数据进行案例测试,以深刻领会算法的核心思想与工程价值。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值