java—我在理解head first的javabean解释时遇到的问题

woobm2wo  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(369)

我正在阅读head first servlet和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> 要获取人员姓名:


我想我明白了-如果请求范围中没有属性,则表示变量person将为null,这也意味着将使用默认构造函数创建新的person对象。底线:我没有我的属性。幸运的是,我以前将person对象存储在请求的作用域中,这意味着它会找到它。
所以我想尝试一下,修改一下代码。而不是 <jsp:useBean id="person" class="foo.Person" scope="request"/> ,我打字 <jsp:useBean id="person" class="foo.Person" scope="application"/> . 请记住,我们的属性以前存储在请求的作用域中,而不是应用程序中,这意味着person将为null。令我惊讶的是,它很容易找到属性并打印出来 Evan . 当这本书清楚地显示它将在我在scope's attribute中所写的同一范围内搜索属性时,这是怎么发生的?

wgxvkvu9

wgxvkvu91#

检查以下描述 <jsp:getProperty> 从javaserver页面™规范
中name属性的值jsp:setproperty and jsp:getproperty will 引用通过pagecontext对象的findattribute方法从其获取的对象。
现在,检查一下 findAttribute 在同一份文件中:
按顺序搜索页、请求、会话(如果有效)和应用程序范围中的命名属性,并返回关联的值或null。
因此,如果属性, person 在中找不到 request 范围,搜索范围扩展到 application 范围。 <jsp:useBean id="person" class="foo.Person" scope="application"/> 将创建一个新的 Person 把它放进 application 无论此属性是否已存在于 request 范围。
当你使用 <jsp:getProperty name="person" property="name"> ,搜索属性, person 将按顺序在页面>请求>会话(如果有效)>应用程序范围中执行,并采用“查找优先”方法,即,一旦找到,就返回值(即不再进行进一步搜索)。
既然你有两个 Person 属性为的对象 person :一个有名字, Evanrequest 范围,另一个作为 new Person()application 范围,在 request 作用域是如何返回的 findAttribute 作品。

ecfdbz9o

ecfdbz9o2#

关键在于 <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);
    }
}

测试.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> 是(如上两个例子所述)。
如有疑问,请参阅jsp规范。
说到这里,请注意 <jsp:useBean> 以及 <jsp:getProperty> 在实践中并不是很常用。人们使用jsp表达式语言、jstl或其他(更强大的)自定义标记。为了从书本中学习并避免使用scriptlet(这是一种糟糕的做法),可以从这些脚本开始,但实际上它们并不是人们最喜欢的访问对象及其属性的方式。

相关问题