2017-01-16 39 views
1

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

<%@ 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的工作原理。

回答

0

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

  • 的jsp:useBean的
  • JSP:的getProperty

的JSP:useBean的

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

一个jsp:useBean动作联营的JAVA编程给定的范围可用具有相同ID的新声明脚本变量 给定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此用户对象(表达)<%=user.getName()%>

的JSP:的getProperty

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

jsp:setProperty和jsp:getProperty中name属性的值将引用通过其findAttribute 方法从pageContext对象获取的对象 。

JSP编译器从jsp:getProperty标签做出了findAttribute()打电话:

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

findAttribute()
搜索页面,要求指定属性,会话(如果有效), 和应用范围,并返回相关值或 null。

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

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

+0

感谢您的澄清。在我看来,这更像是一个设计/开发漏洞,如果'jsp:getProperty'使用'findAttribute'来获得它的值,那么逻辑上我可以去掉''jsp:useBean id =“user”class =“package2JSP.User” scope =“session”/>'line in my jsp file and I should still get namename for''因为'user'仍然在请求中,会话范围。 –

+0

当我试图做到这一点时,我得到了一个异常,这可能意味着当你使用'getProperty'时,bean必须通过'jsp:useBean'定义。好吧,我尝试使用'<%= user.getName()%>'来获得正确的值,正如你所建议的那样,它的工作原理是这里的罪魁祸首绝对是'jsp:getProperty'而不是'jsp:useBean'。 –