2010-04-18 44 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