JSP使用get/setProperty時,Bean的scope 改變引起的問題

來源:互聯網
上載者:User

此文整理自論壇的一個討論文章,我已經加精

其中 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會怎樣嗎??

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.