如何解决我在理解 Head First 的 JavaBean 解释方面的问题
我正在阅读 Head First Servlets 和 JSP,其中一个 servlet 有代码:
protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException {
foo.Person p = new foo.Person("Evan");
req.setAttribute("person",p);
RequestDispatcher view = req.getRequestDispatcher("/result.jsp");
view.forward(req,resp);
}
后来,他们展示了如何使用 <jsp:useBean>
和 <jsp:useProperty>
来获取人名:
我想我明白了 - 如果 request 范围内没有属性意味着变量 person 将为空,这也意味着 new将使用默认构造函数创建 Person 对象。底线:我不会有我的属性。幸运的是,我之前在请求的范围内存储了 Person 对象,这意味着它会找到它。
所以我想尝试一下并稍微更改一下代码。我输入的不是 <jsp:useBean id="person" class="foo.Person" scope="request"/>
,而是 <jsp:useBean id="person" class="foo.Person" scope="application"/>
。请记住,我们的属性之前存储在 request 的范围内,而不是 application,这意味着 person 将为空。令我惊讶的是,它很容易找到了属性并打印了 Evan
。这是怎么发生的,当书清楚地表明它将在我在范围属性中写的相同范围内搜索属性?
解决方法
检查来自JavaServer Pages™Specification的<jsp:getProperty>
的以下描述
jsp:setProperty和jsp:getProperty中name属性的值 将引用从 pageContext 对象获得的对象 通过它的 findAttribute 方法。
现在,检查同一文档中 findAttribute
的描述:
搜索命名属性 在页面、请求、会话(如果有效)和应用程序范围中 order 并返回关联的值或 null。
因此,如果在 person
范围内找不到属性 request
,搜索将扩展到 application
范围。
<jsp:useBean id="person" class="foo.Person" scope="application"/>
将创建一个新的 Person
并将其放入 application
范围,如果该属性不存在,则无论该属性是否已存在于 request
范围中。
当您使用 <jsp:getProperty name="person" property="name">
时,将在 page > request > sessionperson 的搜索/strong>(如果有效)> 应用 范围按顺序和查找优先 方法,即一旦找到,就返回值(即没有进一步的搜索发生)。
因为您有两个 Person
对象,其属性名为 person
:一个具有名称,Evan
在 request
范围内,另一个作为 {{1} }} 在 new Person()
作用域中,application
作用域中的那个是作为 request
工作方式的结果返回的。
关键在于,如果 <jsp:useBean>
在您指定的范围内没有找到对象,它也可以创建一个对象。这意味着:
- 如果对象不在您所说的范围内,
<jsp:useBean>
将创建一个新对象。 - 如果对象在您所说的范围内,
<jsp:useBean>
将使用该对象。
换句话说,您可以处理一个或两个对象,具体取决于您放置对象的上下文以及您所说的上下文。
我知道,这很令人困惑。所以让我们玩一些例子。我将稍微修改 Person 类以显示对象是在哪里创建的。
package test;
public class Person {
private String name;
public Person() {
try {
throw new RuntimeException("Just to see what's going on");
} catch (RuntimeException ex) {
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>");
for (StackTraceElement ste : ex.getStackTrace()) {
System.out.println(ste.toString());
}
System.out.println("<<<<<<<<<<<<<<<<<<<<<<<");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
第一个例子:范围匹配
Servlet 内容:
public class TestController extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
HttpSession session = request.getSession();
session.setAttribute("person",new Person());
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/test.jsp");
requestDispatcher.forward(request,response);
}
}
test.jsp:
<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html>
<body>
<jsp:useBean id="person" class="test.Person" scope="session" />
</body>
</html>
访问 servlet 将导致此输出:
>>>>>>>>>>>>>>>>>>>>>>>>>
test.Person.<init>(Person.java:8)
test.TestController.doGet(TestController.java:21)
javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:744)
<<<<<<<<<<<<<<<<<<<<<<<
查看前两行,您将看到在 servlet 内仅创建了一个对象。 <jsp:useBean>
只是检索这个。
第二个例子:范围不匹配
Servlet 保持不变:
public class TestController extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request,response);
}
}
JSP 现在使用应用程序范围,而不是实际人员所在的会话范围:
<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html>
<body>
<jsp:useBean id="person" class="test.Person" scope="application" />
</body>
</html>
现在的结果是:
>>>>>>>>>>>>>>>>>>>>>>>>>
test.Person.<init>(Person.java:8)
test.TestController.doGet(TestController.java:21)
javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:744)
<<<<<<<<<<<<<<<<<<<<<<<
>>>>>>>>>>>>>>>>>>>>>>>>>
test.Person.<init>(Person.java:8)
org.apache.jsp.test_jsp._jspService(test_jsp.java:71)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
test.TestController.doGet(TestController.java:24)
javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:744)
<<<<<<<<<<<<<<<<<<<<<<<
您现在有两个对象。一个由 servlet 创建,如第一个示例,还有另一个由 JSP 生成的 servlet 创建,因为 <jsp:useBean>
在应用程序范围内找不到对象,所以它使用了 class
属性来创建一个。
混淆是由 <jsp:getProperty>
引起的,它在 page > request > session > application
范围内搜索一个对象,直到找到一个。这与 <jsp:useBean>
的作用不同(如上面两个示例所述)。
如有疑问,请参阅the JSP specs。
话虽如此,请注意 <jsp:useBean>
和 <jsp:getProperty>
在实践中的使用并不多。人们使用 JSP expression language、JSTL 或其他(更强大的)自定义标签。为了从一本书中学习并避免使用 scriptlet(这是一种不好的做法),这些可以帮助您入门,但实际上它们并不是人们最喜欢的访问对象及其属性的方式。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。