2017-01-16 103 views
1

我想了解jsp:useBean JSP動作標籤中的scope屬性的工作原理。在我的理解中,scope用於指示bean所在的位置(請求,會話,應用程序等),但經過一些測試後,我遇到了一個非常有趣的情況,請考慮以下JSP代碼(我正在使用腳本這裏只是爲了簡單起見):jsp:useBean範圍屬性如何工作?

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" 
    pageEncoding="ISO-8859-1" import="package2JSP.User" %> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<title>Title</title> 
</head> 

<body> 
    <% 
     User user1 = new User("id1","name1"); 
     User user2 = new User("id2","name2"); 
     request.setAttribute("user", user1); 
     session.setAttribute("user", user2); 
    %> 
    <%-- Here I expect to create user bean that represents user2 from session scope--%> 
    <jsp:useBean id="user" class="package2JSP.User" scope="session"/> 

    <%-- Here I expect user name to be name2 but it is name1 instead--%> 
    <jsp:getProperty property="name" name="user"/> 
</body> 
</html> 

所以基本上我在這裏創建了2個用戶對象並將其設置爲「用戶」的請求和會話作用域屬性,當我試圖從「會話」檢索「用戶」使用jsp:useBean的範圍似乎是從「請求」範圍中檢索到「用戶」。

你能解釋一下爲什麼發生了嗎?那麼爲什麼jsp:useBean以這種方式工作而不是通常從指定範圍選擇屬性的發展原因是什麼?它有什麼優點嗎?

現在我知道我可以使用JSTL/EL來檢索所需的值,即<c:out value="${sessionScope.user.name}" />但我只是想知道jsp:useBean的工作原理。

回答

0

在這種情況下是2個標籤涉及:

  • 的jsp:useBean的
  • JSP:的getProperty

的JSP:useBean的

根據Specification - CHAPTER JSP.5 - JSP.5.1 <jsp:useBean>

一個jsp:useBean動作聯營的JAVA編程給定的範圍可用具有相同ID的新聲明腳本變量 給定id中定義 語言對象一個實例。 當在無腳本頁面或 無腳本上下文中使用動作時(如在所示動作的主體中),那麼 不會創建Java腳本變量,而是會創建一個EL變量 。

編譯後的Java代碼:

 package2JSP.User user = null; 
     synchronized (session) { 
     user = (package2JSP.User) _jspx_page_context.getAttribute("user", PageContext.SESSION_SCOPE); 
     if (user == null){ 
      try { 
      user = (package2JSP.User) java.beans.Beans.instantiate(this.getClass().getClassLoader(), "package2JSP.User"); 
      } catch (ClassNotFoundException exc) { 
      throw new InstantiationException(exc.getMessage()); 
      } catch (Exception exc) { 
      throw new ServletException("Cannot create bean of class " + "package2JSP.User", exc); 
      } 
      _jspx_page_context.setAttribute("user", user, PageContext.SESSION_SCOPE); 
     } 
     } 

如果你想訪問你可以使用一個scriptlet此用戶對象(表達)<%=user.getName()%>

的JSP:的getProperty

根據Specification - CHAPTER JSP.5 - JSP.5.3 <jsp:getProperty>說:

jsp:setProperty和jsp:getProperty中name屬性的值將引用通過其findAttribute 方法從pageContext對象獲取的對象 。

JSP編譯器從jsp:getProperty標籤做出了findAttribute()打電話:

out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString(
    (((package2JSP.User)_jspx_page_context.findAttribute("user")).getName()))); 

findAttribute()
搜索頁面,要求指定屬性,會話(如果有效), 和應用範圍,並返回相關值或 null。

基本上:返回第一個匹配。

使用useBeangetProperty被認爲是不好的做法。
使用JSTL/EL是使用屬性更好的方法。

+0

感謝您的澄清。在我看來,這更像是一個設計/開發漏洞,如果'jsp:getProperty'使用'findAttribute'來獲得它的值,那麼邏輯上我可以去掉''jsp:useBean id =「user」class =「package2JSP.User」 scope =「session」/>'line in my jsp file and I should still get namename for''因爲'user'仍然在請求中,會話範圍。 –

+0

當我試圖做到這一點時,我得到了一個異常,這可能意味着當你使用'getProperty'時,bean必須通過'jsp:useBean'定義。好吧,我嘗試使用'<%= user.getName()%>'來獲得正確的值,正如你所建議的那樣,它的工作原理是這裏的罪魁禍首絕對是'jsp:getProperty'而不是'jsp:useBean'。 –