zoukankan      html  css  js  c++  java
  • 【Head First Servlets and JSP】笔记7:如何创建一个全局的dog?

    重定向与请求分派

    “局部”参数——ServletConfig——servlet初始化参数

    “全局”参数——ServletContext——上下文初始化参数

    Web app的“构造器”——ServletContextListener

    实战:如何创建一个全局的dog?

    1、重定向与请求分派。

            resp.sendRedirect("http://www.cnblogs.com/xkxf/");
            RequestDispatcher view = req.getRequestDispatcher("result.jsp"); // 为JSP实例化一个请求分派器
    
            view.forward(req, resp); // 使用请求分派器要求容器准备好JSP,并向JSP发送请求和响应
    • 重定向由客户端完成,请求分派由服务器完成。
    • 重定向是让客户完成工作,而请求分派要求服务器上的某某来完成任务。

    2、在页面中显示email。

    很显然,不可能通过硬编码来完成。而是需要从数据库拿数据,可以想象这个过程,当我们点开某个社交网站,然后点开“个人资料”,这个时候servlet中会调用一个getEmail的方法得到email,之后把它传给视图,最后展示给用户。

    那么,有没必要在部署描述文件(DD,deployment descriptor)中存储email呢?假设你写搭建一个个人博客、编辑一份网页简历,这是有可能的,总要好过硬编码在html中。

    3、还是需要快速搭建一个测试环境,沿用上一节的代码。

    4、如何在DD中添加email呢?如下所示:

    先修改web.xml,

    <?xml version="1.0" encoding="ISO-8859-1" ?>
    
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
             version="2.4">
    
        <servlet>
            <servlet-name>MyTest</servlet-name>
            <servlet-class>com.example.web.MyTest</servlet-class>
            
            <init-param>
                <param-name>email</param-name>
                <param-value>wyzxk_fx@163.com</param-value>
            </init-param>
            
        </servlet>
    
        <servlet-mapping>
            <servlet-name>MyTest</servlet-name>
            <url-pattern>/MyTest.do</url-pattern>
        </servlet-mapping>
    
    </web-app>

     修改servlet,

    package com.example.web;
    
            import javax.servlet.*;
            import javax.servlet.http.*;
            import java.io.*;
    
    public class MyTest extends HttpServlet {
        public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
            resp.setContentType("text/html");
    
            PrintWriter out = resp.getWriter();
            out.println(getServletConfig().getInitParameter("email"));
            // 这里相当于调用this.getServletConfig().ge...,this是谁呢?this是一个HttpServlet对象。
        }
    }

    重启Tomcat,点击submit,可以看到

    BTW:需要注意的是,不能在构造函数中调用getServletConfig(),原因是在这个时候ServletConfig根本不存在!

    package javax.servlet;
    
    import java.io.IOException;
    
    public interface Servlet {
        void init(ServletConfig var1) throws ServletException;
    
        ServletConfig getServletConfig();
    
        void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
    
        String getServletInfo();
    
        void destroy();
    }

    回忆一下servlet的生命周期,servlet的生命周期由Web容器所掌控,Web容器首先调用Servlet的构造函数,在这之后才调用Servlet的init()函数。观察上面的代码,可以发现init()的参数正是ServletConfig。实际情况是这样的:

    • 容器初始化一个servlet的时候,会为这个servlet建立一个唯一的ServletConfig。
    • 容器从DD(也就是web.xml)中“读出”ServletConfig(也就是init-param)并把这些参数交给ServletConfig。然后把ServletConfig传递给servlet的init()方法。

    5、有时候,需要一个更“全局”的参数,在Web的世界里,它被叫做上下文初始化参数,与servlet初始化参数不同的是,它的有效范围是整个Web App,而不仅仅是一个servlet。设置方法为:

    <?xml version="1.0" encoding="ISO-8859-1" ?>
    
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
             version="2.4">
    
        <context-param>
            <param-name>email</param-name>
            <param-value>wyzxk_fx@163.com</param-value>
        </context-param>
    
        <servlet>
            <servlet-name>MyTest</servlet-name>
            <servlet-class>com.example.web.MyTest</servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>MyTest</servlet-name>
            <url-pattern>/MyTest.do</url-pattern>
        </servlet-mapping>
    
        <!--在这之后,还可以以有更多的servlet,而context-param是对所有servlet有效的!-->
    
    </web-app>

    调用的方式与servlet初始化参数类似:

    package com.example.web;
    
            import javax.servlet.*;
            import javax.servlet.http.*;
            import java.io.*;
    
    public class MyTest extends HttpServlet {
        public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
            resp.setContentType("text/html");
    
            PrintWriter out = resp.getWriter();
            // out.println(getServletConfig().getInitParameter("email"));
            out.println(getServletContext().getInitParameter("email"));
            // 只需要把Config改成Context就Ok了!
        }
    }

    重启tomcat之后,点击submit,仍旧会得到相同的输出页面,对用户来说,不会体验到任何差别!不过需要再次强调:每个servlet有一个ServletConfig,每个Web应用有一个ServletContext。

    6、在一些场合下,我们希望有一些代码在Web应用提供服务之前,首先被执行,类似于通过“静态加载块”来加载数据库连接,也就是在程序正式工作前,完成一些初始化工作,例如,创建一个“全局”的数据库连接,或是其它的全局对象,这就需要用到ServletContextListener

    我们知道,完成一个事件响应,首先需要实现接口,然后注册事件,最后写响应方法。那么,这个Listener应该由谁来注册呢?如何使用这个监听者呢?

     

    7、一个简单的ServletContextListener:如何创建一个全局的dog?

    package com.example;
    
    public class Dog {
        private String breed;
    
        public Dog(String breed) {
            this.breed = breed;
        }
    
        public String getBreed() {
            return breed;
        }
    }
    <?xml version="1.0" encoding="ISO-8859-1" ?>
    
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
             version="2.4">
    
        <servlet>
            <servlet-name>ListenerTester</servlet-name>
            <servlet-class>com.example.ListenerTester</servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>ListenerTester</servlet-name>
            <url-pattern>/ListenerTester.do</url-pattern>
        </servlet-mapping>
    
    
        <context-param>
            <param-name>breed</param-name>
            <param-value>Great Dane</param-value>
        </context-param>
    
        <listener>
            <listener-class>
                com.example.MyServletContextListener
                <!--在初始化任何servlet之前初始化应用-->
            </listener-class>
        </listener>
    
    </web-app>
    package com.example;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    public class MyServletContextListener implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            ServletContext servletContext = servletContextEvent.getServletContext();
            String breed = servletContext.getInitParameter("breed");
            
            Dog dog = new Dog(breed);
            servletContext.setAttribute("dog", dog);
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
    
        }
    }
    package com.example;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.*;
    import java.io.*;
    
    public class ListenerTester extends HttpServlet {
        @Override
        public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setContentType("text/html");
            PrintWriter out = resp.getWriter();
    
            out.println("test context attribute set by listener <br />");
            out.println("<br />");
    
            Dog dog = (Dog)getServletContext().getAttribute("dog");
            out.println("Dog's breed is: " + dog.getBreed());
        }
    }
  • 相关阅读:
    Sharepoint COMException 0x81020037
    [SharePoint]如何去掉欢迎导航的信息?
    配置两台Azure服务器,一台加入另一台的ad域加入不进去的问题
    在Azure上部署Sqlserver网络访问不了的问题
    Page 由于代码已经过优化或者本机框架位于调用堆栈之上
    ProjectOnline同步数据到线下
    关于ProjectServer定制化项目中心页面
    oracle数据库逐步学习总结【基础二】
    Java学习个人总结
    oracle数据库逐步学习总结【基础一】
  • 原文地址:https://www.cnblogs.com/xkxf/p/6931798.html
Copyright © 2011-2022 走看看