2010-04-18 42 views
9

比方說,我有一個簡單的登錄servlet,用於檢查傳遞的name並創建User對象並將其存儲在會話中。訪問相同會話bean的Java servlet和JSP

User user = new User(); 
user.setId(name); 

request.getSession().setAttribute("user", user); 
response.sendRedirect("index.jsp"); 

index.jsp頁我通過jsp:useBean

<jsp:useBean id="user" scope="session" 
      class="package.name.User"/> 

<div class="panel"> 
    Welcome ${user.id} 
</div> 

訪問用戶對象它的工作至今。

從JSP豆文檔

要找到或實例化Bean時, 採取以下 步驟,順序如下:

  1. 嘗試找到一個Bean的範圍和名稱你指定。
  2. 使用您指定的名稱定義對象引用變量。
  3. 如果發現Bean,則在變量中存儲對它的引用。如果你指定了 類型,則給出Bean 該類型。
  4. 如果沒有找到Bean,請從 指定的類中實例化它,並在 中存儲對該變量的引用。如果類名稱 代表序列化模板,則 Bean將通過 java.beans.Beans.instantiate實例化。
  5. 如果已經實例化(而不是位於)Bean,並且它具有正文標籤或元素(在 和之間),則 將執行正文標籤。

的問題:

嘗試找到一個Bean的範圍和名稱指定

它沒有指定的 「定位」 的過程。這是否意味着它會檢查HttpServletRequest.getSession()或只檢查其他頁面是否已經創建了這個bean?

如果沒有找到Bean,則從您指定的類中實例化它,將它的引用存儲在新變量中。

這實際上意味着JSP可以使用jsp_internal_name_user會話新創建的bean關聯。 沒有關於Jsp如何在會話中存儲和發現bean的信息。

有一個選項可以使用${sessionScope.user}來訪問會話對象,並且可以保證Java會話對象中的「用戶」將被獲取。我自己也一樣。

Java EE 5示例「Book Store」使用${sessionScope.name}訪問會話對象的方法。

只使用${user}的作品。這就是我所擔心的。我希望在規範中看到關於locate進程的特定語句以及${user}是否必須工作,或者它是否符合JSP和/或JSTL參考實現。

回答

6

如果控制器(servlet)注意模型,jsp:useBean僅在缺省實例(由無參數構造函數構造)暴露與不存在實例不同的行爲/狀態時纔有用。例如。如果你想有一個默認的用戶名「未知用戶」,你會怎麼做:

public User { 
    this.id = "Unknown User"; 
} 

否則最終用戶可能面臨一個「歡迎光臨」,而不是「歡迎未知用戶」顯示。在你的特定情況下,你可以安全地刪除它。這是多餘的。

但是,我也看到了它對純文檔很有用的論點。您可以在JSP頁面頂部聲明「無用的」jsp:useBean實例,以便您可以概覽在特定的JSP頁面中確切使用了哪些模型。雖然我覺得它非常聰明,但我自己從來沒有這樣需要在JSP中記錄模型的方法。根據評論,另一個論點的確如此,IDE就像IDEA和Eclipse能夠在EL中自動完成bean屬性。

更新:對於定位,它使用PageContext#findAttribute()作爲它,然後使用反射/ javabean introspection調用getter方法。例如。

${user.name} 

大致解析

out.print(pageContext.findAttribute("user").getName()) 

另見JSP specificationJSP EL specification

更新2:在<jsp:useBean>肯定不使用內部名稱或以會話屬性前綴。遍歷所有會話屬性自己,看看實際的鍵和值:

<c:forEach items="${sessionScope}" var="entry"> 
    ${entry.key} = ${entry.value}<br> 
</c:forEach> 

或在servlet

for (String name : Collections.list(session.getAttributeNames())) { 
    System.out.println(name + " = " + session.getAttribute(name)); 
} 
+0

有一些文件,其中明確描述變量在JSP頁面解析的過程? – 2010-04-18 18:52:43

+0

Intellij IDEA僅在顯式聲明的情況下完成變量字段。 – 2010-04-18 18:54:21

+1

1)你在談論EL嗎?檢查[JSP EL規範](https://jsp.dev.java.net/spec/jsp-2_1-fr-spec-el.pdf)。簡而言之,它執行'PageContext#findAttribute()'來查找任何作用域中的屬性。 2)這也是我以前見過的另一個論點。 – BalusC 2010-04-18 18:57:56

2

從文檔:

<jsp:useBean>元件定位或實例化一個JavaBeans組件。 <jsp:useBean>首次嘗試查找Bean的實例。 如果Bean不存在,<jsp:useBean>將從類或序列化的 模板中對其進行實例化。

由於「定位」的豆是完全好吧那麼我們可以假定豆可以通過經由<jsp:useBean>比實例化其他手段來提供。例如,通過在servlet中創建它。

4

引述JSP規範JSP.5。1

基本語義嘗試使用id和 作用域來查找現有對象。如果未找到該對象,它將嘗試使用其他 屬性創建該對象。

換句話說,

<jsp:useBean id="user" scope="session" class="package.name.User"/> 

將轉化大致可分爲Java作爲:

package.name.User user = (package.name.User)session.getAttribute("user"); 
if (user == null){ 
    user = new package.name.User(); 
    session.setAttribute("user", user); 
} 
+0

嗨,很高興在這裏看到你:)你的答案對於特定的'jsp:usebean'行來說確實是正確的,你只會在'if'塊中忘記'session.setAttribute(「user」,user)';) – BalusC 2010-04-19 21:22:50

+0

我希望看到「查找現有」過程的描述。實際上jsp可以使用「user_jsp_internal」名稱存儲對象。 – 2010-04-20 11:02:59

+0

不,它沒有。該對象與'id'中指定的屬性鍵一起存儲。您還可以通過'$ {user}'在普通EL中訪問它,等等。 – BalusC 2010-04-20 17:34:40