1

我试图了解JSP 动作标签scope中的属性究竟是如何工作的。jsp:useBean在我的理解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 个用户对象并将它们设置为请求和会话范围中的“用户”属性,当我尝试从“会话”范围检索“用户”时jsp:useBean,似乎从“请求”范围检索“用户” .

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

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

4

1 回答 1

0

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

  • jsp:useBean
  • jsp:getProperty

jsp:useBean

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

jsp:useBean 操作将在给定范围内定义 并具有给定 id 的 Java 编程语言对象的实例与新声明的具有相同 id 的脚本变量相关联。当在无脚本页面或无脚本上下文中使用操作时(如在指示的操作主体中),不会创建 Java 脚本变量,而是创建 EL 变量。

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

如果你想访问这个用户对象,你可以使用 scriptlet(expression)<%=user.getName()%>

jsp:getProperty

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

jsp:setProperty 和 jsp:getProperty 中的 name 属性值将引用一个对象,该对象是通过 pageContext 对象的 findAttribute 方法获取的。

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

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

findAttribute()
按顺序在页面、请求、会话(如果有效)和应用程序范围中搜索命名属性,并返回关联的值或 null。

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

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

于 2017-01-25T19:51:00.683 回答