Java servlet和JSP访问同一个会话bean

时间:2010-04-18 16:57:23

标签: java jsp servlets

假设我有一个简单的Login servlet,它检查传递的name并创建User对象并将其存储在会话中。

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 beans文档

  

要找到或实例化Bean,    采取以下措施   步骤,按此顺序:

     
      
  1. 尝试使用您指定的范围和名称查找Bean。
  2.   
  3. 使用您指定的名称定义对象引用变量。
  4.   
  5. 如果找到Bean,则在变量中存储对它的引用。如果   你指定了类型,给出了Bean   那种。
  6.   
  7. 如果找不到Bean,请从类中实例化它   指定,存储对它的引用   新变量。如果是班级名称   代表一个序列化的模板,   Bean由实例化实例化   java.beans.Beans.instantiate联合。
  8.   
  9. 如果已实例化(而非定位)Bean,以及是否   它有身体标签或元素(之间    和),   执行身体标签。
  10.   

问题:

  

尝试使用您指定的范围和名称查找Bean

它没有指定“定位”过程。这是否意味着它会检查HttpServletRequest.getSession()或只是检查其他页面是否已经创建了这个bean?

  

如果找不到Bean,请从您指定的类中实例化它,并存储&gt;在新变量中引用它。

这实际上意味着Jsp可以使用 jsp_internal_name_user 将新创建的bean与会话相关联。 没有关于Jsp如何在会话中存储和查找bean的信息。

有一个选项可以使用${sessionScope.user}访问会话对象,这将保证来自Java会话对象的“用户”。我自己投入的那个。

Java EE 5示例“Book Store”使用${sessionScope.name}方法访问会话对象。

仅使用${user}作品。这就是让我担心的问题。我希望在规范中看到关于locate进程的特定句子,以及${user}是否必须有效,或者是否由JSP和/或JSTL参考实现决定。

3 个答案:

答案 0 :(得分:6)

如果控制器(servlet)负责模型,jsp:useBean仅在默认实例(使用no-arg构造函数构造)公开不同的行为/状态时才有用。实例。例如。如果您希望使用默认用户名“未知用户”,则可以执行以下操作:

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

否则,最终用户可能会面对“欢迎”而不是“欢迎未知用户”显示。在您的特定情况下,您可以安全地删除它。这是多余的。

但是,我也看到了它对纯文档有用的论点。您可以在JSP页面顶部声明“无用的”jsp:useBean实例,以便您可以概览在特定JSP页面中使用的模型。虽然我发现它非常聪明,但我自己从未需要这种在JSP中记录模型的方法。根据评论,另一个论点确实是IDE这样的IDEA和Eclipse能够在EL中自动完成bean属性。

更新:关于定位,它使用PageContext#findAttribute(),然后使用reflection / javabean introspection来调用getter方法。 E.g。

${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));
}

答案 1 :(得分: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);
}

答案 2 :(得分:2)

来自文档:

  

<jsp:useBean>元素定位或实例化JavaBeans组件。   <jsp:useBean>首先尝试查找Bean的实例。   如果Bean不存在,<jsp:useBean>将从类或序列化实例化它   模板。

由于“定位”bean完全没问题,因此我们可以假设bean可以通过<jsp:useBean>实例化以外的方式使用。例如,通过在servlet中创建它。