我在理解 Head First Java Bean 解释时遇到的问题
My problem in understanding Head First's JavaBean explanation
我正在阅读 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>
的以下描述
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.
现在,检查同一文档中 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.
因此,如果在 request
范围内找不到属性 person
,搜索将扩大到 application
范围。
<jsp:useBean id="person" class="foo.Person" scope="application"/>
将创建一个新的 Person
并将其放入 application
范围(如果不存在),无论此属性是否已存在于 request
范围。
当您使用 <jsp:getProperty name="person" property="name">
时,搜索属性 person
将在 page > request[=49 上执行=] > session(如果有效)> application scope(s) 按顺序和 find-first 方法,即一旦找到,就返回该值(即不再进行进一步搜索)。
因为你有两个 Person
属性名为 person
的对象:一个在 request
范围内的名称为 Evan
,另一个为 new Person()
在 application
范围内,request
范围内的那个作为 findAttribute
工作方式的结果返回。
要点是 <jsp:useBean>
如果在您指定的范围内找不到对象,也可以创建一个对象。这意味着:
- 如果对象不在您所说的范围内,
<jsp:useBean>
将创建一个新对象。
- 如果对象在您所说的范围内,
<jsp:useBean>
将使用该对象。
换句话说,您可以处理一个对象或两个对象,具体取决于您放置该对象的上下文以及您所说的上下文。
我知道,这令人困惑。所以让我们玩一些例子。我将屠杀 Person class 一点以显示对象的创建位置。
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, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.setAttribute("person", new Person());
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/test.jsp");
requestDispatcher.forward(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(这是一种不好的做法),这些可以帮助您入门,但实际上它们并不是人们真正喜欢的访问对象及其属性的方式。
我正在阅读 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>
的以下描述
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.
现在,检查同一文档中 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.
因此,如果在 request
范围内找不到属性 person
,搜索将扩大到 application
范围。
<jsp:useBean id="person" class="foo.Person" scope="application"/>
将创建一个新的 Person
并将其放入 application
范围(如果不存在),无论此属性是否已存在于 request
范围。
当您使用 <jsp:getProperty name="person" property="name">
时,搜索属性 person
将在 page > request[=49 上执行=] > session(如果有效)> application scope(s) 按顺序和 find-first 方法,即一旦找到,就返回该值(即不再进行进一步搜索)。
因为你有两个 Person
属性名为 person
的对象:一个在 request
范围内的名称为 Evan
,另一个为 new Person()
在 application
范围内,request
范围内的那个作为 findAttribute
工作方式的结果返回。
要点是 <jsp:useBean>
如果在您指定的范围内找不到对象,也可以创建一个对象。这意味着:
- 如果对象不在您所说的范围内,
<jsp:useBean>
将创建一个新对象。 - 如果对象在您所说的范围内,
<jsp:useBean>
将使用该对象。
换句话说,您可以处理一个对象或两个对象,具体取决于您放置该对象的上下文以及您所说的上下文。
我知道,这令人困惑。所以让我们玩一些例子。我将屠杀 Person class 一点以显示对象的创建位置。
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, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.setAttribute("person", new Person());
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/test.jsp");
requestDispatcher.forward(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(这是一种不好的做法),这些可以帮助您入门,但实际上它们并不是人们真正喜欢的访问对象及其属性的方式。