jsp:useBean 范围属性如何工作?

how does jsp:useBean scope attribute work?

我想了解 jsp:useBean JSP 操作标签中的 scope 属性究竟是如何工作的。在我的理解中 scope 用于指示 bean 所在的位置(请求、会话、应用程序等),但经过一些测试后我遇到了一个有趣的情况,但情况并非如此,请考虑以下 JSP 代码(为了简单起见,我在这里使用 scriplets):

<%@ 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 个用户对象并将它们设置为请求和会话范围中的 "user" 属性,当我尝试使用 [=13 从 "session" 范围检索 "user" =] 似乎从 "request" 范围中检索到了 "user"。

你能解释一下为什么会这样吗?使 jsp:useBean 以这种方式工作而不是通常从指定范围中选择属性的开发原因是什么,它有什么优点吗?

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

在这种情况下涉及 2 个标签:

  • jsp:useBean
  • jsp:getProperty

jsp:useBean

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

A jsp:useBean action associates an instance of a Java programming language object defined within a given scope and available with a given id with a newly declared scripting variable of the same id . When a action is used in an scriptless page, or in an scriptless context (as in the body of an action so indicated), there are no Java scripting variables created but instead an EL variable is created.

编译后的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);
        }
      }

如果你想访问这个用户对象,你可以使用脚本(表达式)<%=user.getName()%>

jsp:getProperty

根据Specification - CHAPTER JSP.5 - JSP.5.3 <jsp:getProperty>说:

The value of the name attribute in jsp:setProperty and jsp:getProperty will refer to an object that is obtained from the pageContext object through its findAttribute method.

JSP 编译器从 jsp:getProperty 标记调用 findAttribute()

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

findAttribute()
Searches for the named attribute in page, request, session (if valid), and application scope(s) in order and returns the value associated or null.

基本上:返回第一个匹配项。

使用 useBeangetProperty 被认为是不好的做法。
使用 JSTL/EL 是处理属性的更好方法。