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

Myk*_*yev 10 java jsp servlets

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

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

request.getSession().setAttribute("user", user);
response.sendRedirect("index.jsp");
Run Code Online (Sandbox Code Playgroud)

index.jsp页面中,我通过访问用户对象jsp:useBean

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

<div class="panel">
    Welcome ${user.id}
</div>
Run Code Online (Sandbox Code Playgroud)

它到目前为止工作.

来自jsp beans文档

要找到或实例化Bean,请按以下顺序执行以下步骤:

  1. 尝试使用您指定的范围和名称查找Bean.
  2. 使用您指定的名称定义对象引用变量.
  3. 如果找到Bean,则在变量中存储对它的引用.如果指定了type,则为Bean提供类型.
  4. 如果找不到Bean,则从您指定的类中实例化它,在新变量中存储对它的引用.如果类名表示序列化模板,则Bean由java.beans.Beans.instantiate实例化.
  5. 如果已实例化(而不是定位)Bean,并且它具有正文标记或元素(在和之间),则执行body标记.

问题:

尝试使用您指定的范围和名称查找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参考实现决定.

Bal*_*usC 6

如果控制器(servlet)负责模型,jsp:useBean则只有在默认实例(使用no-arg构造函数构造)暴露不同的行为/状态而不是不存在的实例时才有用.例如,如果您希望使用默认用户名"未知用户",则可以执行以下操作:

public User {
    this.id = "Unknown User";
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

${user.name}
Run Code Online (Sandbox Code Playgroud)

大致解决了

out.print(pageContext.findAttribute("user").getName())
Run Code Online (Sandbox Code Playgroud)

另请参阅JSP规范JSP EL规范.

更新2:<jsp:useBean> 当然不使用内部名称或会话属性前缀.自己遍历所有会话属性以查看实际的键和值:

<c:forEach items="${sessionScope}" var="entry">
    ${entry.key} = ${entry.value}<br>
</c:forEach>
Run Code Online (Sandbox Code Playgroud)

或者在servlet中

for (String name : Collections.list(session.getAttributeNames())) {
   System.out.println(name + " = " + session.getAttribute(name));
}
Run Code Online (Sandbox Code Playgroud)


evn*_*ets 5

引用 JSP 规范 JSP.5.1

基本语义尝试使用 id 和范围查找现有对象。如果未找到对象,它将尝试使用其他属性创建对象。

换句话说,

<jsp:useBean id="user" scope="session" class="package.name.User"/>
Run Code Online (Sandbox Code Playgroud)

将大致翻译成 java 为:

package.name.User user = (package.name.User)session.getAttribute("user");
if (user == null){
  user = new package.name.User();
  session.setAttribute("user", user);
}
Run Code Online (Sandbox Code Playgroud)