【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>[email protected]</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>[email protected]</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());
    }
}
时间: 2024-07-30 13:53:07

【Head First Servlets and JSP】笔记7:如何创建一个全局的dog?的相关文章

天书笔记:如何创建一个现代的footer(页脚)

此笔记纯属本人脑残笔记,阅读困难不理解属正常现象,初学者尽量不要阅读,否则轻则口吐白沫重则走火入魔,切记切记 老规矩,效果图 这个布局也是从b站看到的,回来自己实现了一遍 HTML: <div class="foot"> <div class="footbody"> <div class="itembox"> <span class="box_itemtitle">链接块标题&l

QT学习笔记1:创建一个QT的空项目

初始QT,在创建QT项目时系统提供了几个不同的模板,点选模板,系统会自动为用户创建好一个基础框架方便开发. 这里,我们试着不适用系统提供的基础框架,自己创建一个空的QT项目. 1.创建工程 (1)进入QT界面,选择新建工程,在跳出的选项中选择其他项目—空的Qt项目,选择继续. (2)为项目取名为blankProject,选择下一步. (3)添加工程信息. 创建完成后,系统会自动创建一个名为blankProject.pro的文件,为工程启动文件.为工程添加信息,工程创建完成. 1 # QT bla

【Head First Servlets and JSP】笔记23:Expression Language(EL) 完全攻略

基本上是<Head First Servlets and JSP>内容的整理.扩充.顺便推荐一个供参考的JSP教程:JSP Tutorial内容很全面,还有一些有趣的实例. 完整代码参考 EL隐式对象汇总 pageContext使用参考 EL表达式的基本规则 关于EL的一些细节 通过EL获得request参数 从request得到更多信息 获得Request Method? xxxxScope有意义吗? 通过EL调用函数 EL与数学运算 1.EL隐式对象汇总.如下所示: 更详细的内容可以参考 

【Head First Servlets and JSP】笔记1

1.把Java放到HTML中,JSP应运而生. 2.Servlet本身并没有main()方法,所以必须要有其他Java程序去调用它,这个Java程序就是Web容器(Container).Tomcat就是一个容器. 3.容器能提供什么? 通信支持 -不用再写ServerSocket了 生命周期管理 -容器控制着Servlet的生与死 多线程支持 -容器会自动地为它接收的每一个Servlet请求创建一个新的Java线程 声明方式实现安全 JSP支持 -容器负责把JSP代码翻译成Java 4.容器如何

JSP笔记02——概述(译)

不完全翻译,结合谷歌,一定主观性,还可能有误,原始内容地址:https://www.tutorialspoint.com/jsp/jsp_overview.htm 主要内容如下: 什么是JSP? 为什么使用JSP? 什么是JSP? JavaServer Pages (JSP)是一种用于开发支持动态内容的Web页面的技术.开发人员可以通过使用特殊的JSP标签在HTML页面中插入Java代码,这些标签大部分以<%开头,以%>结尾. [注释]感觉直接用英文全名称呼好一点.. JSP事实上是一种Jav

【Head First Servlets and JSP】实践记录01:从有脚本到无脚本

试图章节式的阅读<Head First Servlets and JSP>总感觉不对劲,这本书前后的联系性很强,有点类似于“连续剧”,而不是通常的“知识清单”. 可以建立多态的bean引用吗 使用type,但没有class scope属性默认为“page” 从有脚本到无脚本 1.快速搭建一个测试环境:输入用户名,返回“Hello, 用户名” index.html <!DOCTYPE html> <html lang="en"> <head>

JSP笔记

溪云初起日沉阁,山雨欲来风满楼.--唐代许浑<咸阳城东楼 / 咸阳城西楼晚眺 / 西门> JSP基本语法 脚本标识 JSP 表达式 <%= 表达式%> 向页面输出信息 声明标识 <%! 声明的方法和变量的代码 %> <%! String s = "胖子"; int add(int x,int y){ return x+y; } %> 代码片段 <% java代码或是脚本代码 %> <% out.print("这

JSP笔记(二)

session session表示客户端与服务器的一次回话 Web中的session指的是用户在浏览器某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间 从以上定义中可以看到,session实际上是一个特定的时间概念 在服务器的内存中保存着不同的用户的session Session对象 Session对象是一个JSP内置对象 Session对象在第一个JSP页面被装载时自动创建,完成会话期管理 从一个客户打开浏览器并连接服务器开始,到客户关闭浏览器离开这个服务

JSP笔记——5.九个内置对象

之所以叫它们对象,是因为它们是Servlet API接口的实例.而之所以叫内置,是因为jsp对烦了对他们的初始化.在jsp对应的servlet文件中的_jspService()方法中这些实例将会被创建.这9个内置对象分别为:application.config.exception.out.page.pageContext.request.response.session.虽然这里也出现了request,page,application,session,但是请千万要弄清楚内置对象与作用域的区别.这