Servlet处理流程分析

    xiaoxiao2021-03-30  35

    ---------------siwuxie095

      

      

      

      

      

      

      

      

    Tomcat 处理客户端请求的方式:

      

    Tomcat 既是一个 Servlet 容器,又具有 Web 服务器的功能,

    也即 拥有处理静态 HTML 页面的能力

      

    只不过相对于Apache、Nginx 等专业的 Web 服务器而言,

    其功能又弱一些

      

      

      

      

    客户端从发起请求,到接收响应的处理流程:

      

    1)客户端发送HTTP 请求,该请求会首先到达 Tomcat 内置的 Web 服务器

      

      

    2)Tomcat 内置的 Web 服务器接收到请求后,将请求转发给 Servlet 容器

      

      

    3)Servlet 容器接收到请求后,加载 Servlet,产生 Servlet 实例后,会向其

    传递表示请求响应的对象,然后Servlet 实例使用 请求对象,得到客户端的

    请求信息,并进行响应处理

      

    「请求响应对象,即HttpServletRequest 对象 和 HttpServletResponse 对象」

      

      

    4)该Servlet 处理完毕之后,有可能会将请求转发给其他的 Servlet 继续进行处理

      

      

    5)全部处理完毕后,处理结果通过响应对象,发送回客户端。

    至此,一个客户端请求处理完毕

      

      

      

      

      

    Servlet 的执行流程:

      

    1)当Servlet 被装载并实例化后,Servlet 容器会首先调用 init() 方法

    对 Servlet 进行初始化,只有在init() 方法调用成功后,Servlet 才能处于

    服务状态,接收客户端的请求并进行处理

      

    init() 方法在Servlet 的生命周期中只会被调用一次

      

      

    2)当Servlet 执行完初始化操作,就会调用service() 方法来对客户端

    的请求进行处理

      

    service() 方法在Servlet 的生命周期中会被调用多次,这和请求次数有关

      

      

    3)当Servlet 不再使用,Servlet 容器销毁 Servlet 实例之前,

    会调用 destroy() 方法

      

    destroy() 方法在 Servlet 的生命周期中也只会被调用一次

      

      

      

      

    工程结构目录如下:

      

      

      

     

    HelloServlet.java:

      

    package com.siwuxie095.servlet;

      

    import java.io.IOException;

    import java.io.PrintWriter;

      

    import javax.servlet.ServletConfig;

    import javax.servlet.ServletException;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

      

    //HelloServlet 继承自 HttpServlet

    public class HelloServlet extends HttpServlet {

     

    /**

    * 先覆盖父类 HttpServlet 的方法:

    * 右键->Source->Override/Implement methods

    * 选择 HttpServlet service() GenericServlet init() destroy()

    *

    * 这样,HelloServlet 的骨架生成完毕

    */

     

    @Override

    publicvoid init() throws ServletException {

    System.out.println("===== init without parameters =====");

    super.init();

    }

      

    @Override

    publicvoid init(ServletConfig config) throws ServletException {

    System.out.println("===== init with parameters =====");

    super.init(config);

    }

      

    @Override

    protectedvoid service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    System.out.println("===== service =====");

    //通过 HttpServletResponse 获取一个 PrintWriter 对象

    //PrintWriter是一个以字符为单位的输出流

    PrintWriter pw=resp.getWriter();

    pw.println("Hello World");

    //输出完毕,关闭流

    pw.close();

    }

      

    @Override

    publicvoid destroy() {

    System.out.println("===== destroy =====");

    super.destroy();

    }

      

      

    }

      

      

    在部署描述符 web.xml 中注册 servlet:

      

    <?xmlversion="1.0"encoding="UTF-8"?>

    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1">

    <display-name>HelloServlet</display-name>

    <welcome-file-list>

    <welcome-file>index.html</welcome-file>

    <welcome-file>index.htm</welcome-file>

    <welcome-file>index.jsp</welcome-file>

    <welcome-file>default.html</welcome-file>

    <welcome-file>default.htm</welcome-file>

    <welcome-file>default.jsp</welcome-file>

    </welcome-file-list>

     

    <!-- 添加一个 servlet 元素,它有两个子元素 -->

    <!-- servlet 元素用于注册 servlet -->

    <!-- servlet-name 用于设置 servlet 的注册名称(可随意设置) -->

    <!-- servlet-name 用于设置 servlet 的完全限定名 -->

    <servlet>

    <servlet-name>HelloServlet</servlet-name>

    <servlet-class>com.siwuxie095.servlet.HelloServlet</servlet-class>

    </servlet>

     

    <!-- 添加一个 servlet-mapping 元素,它有两个子元素 -->

    <!-- servlet-mapping 元素用于映射 servlet 对外访问的路径 -->

    <!-- servlet-name 也是指 servlet 的注册名称,需保持一致 -->

    <!-- servlet-name servlet servlet-mapping 联系起来的唯一标志 -->

    <!-- url-pattern 用于指定 servlet 对外访问的路径 -->

    <servlet-mapping>

    <servlet-name>HelloServlet</servlet-name>

    <url-pattern>/Hello</url-pattern>

    </servlet-mapping>

     

    </web-app>

      

      

    部署描述符web.xml 在 WEB-INF 目录下,如果没有,手动创建即可

      

    选择工程 HelloServlet,右键->Java EE Tools->Generate Deployment Descriptor Stub

      

      

      

    注意:

      

    init() 方法有两个:没有参数的 和 有参数的

      

    推荐重写无参的 init() 方法,因为重写无参的init() 方法,

    无需手动调用 super.init() 方法,即 可以删除 或 注释掉

      

    如果重写有参的init() 方法,则必须手动调用 super.init() 方法

      

    重写init() 方法并不是必须的,如果要在 Servlet 实例化时,执行

    一些初始化操作,才重写init() 方法

      

      

      

    选择Tomcat,右键->Add and Remove,把 HelloServlet 添加到 Tomcat 中

      

    启动Tomcat,控制台只有 Tomcat 的启动日志,而 HelloServlet 的方法体中

    的日志信息并没有打印出来,说明在没有访问之前,Servlet 是没有实例化的

      

    在浏览器中输入:localhost:8080/HelloServlet/Hello进行访问,控制台输出:

      

      

      

    通过日志信息可以看出:

    先执行有参的init() 方法,再执行无参的 init() 方法,最后执行service() 方法

      

      

    有参的init() 方法的父类实现:

      

      

      

    无参的init() 方法的父类实现:

      

      

      

    有参的init() 方法的父类实现中显式的调用了无参的 init() 方法,这是

    两个 init() 方法的日志信息都被打印出来的原因

      

      

      

    此时,关闭Tomcat,destroy() 方法的日志信息并没有打印,

    说明 destroy() 方法没有调用

      

    「当Servlet 容器销毁 Servlet 实例时,才会调用 destroy() 方法」

      

      

      

    Servlet 容器销毁 Servlet 实例的过程:

      

    HelloServlet 导出到 Tomcat 安装目录的 webapps 目录下

      

      

      

    CMD 窗口中输入 startup 或 startup.bat,启动 Tomcat 并监视日志输出

      

    在浏览器输入:localhost:8080/HelloServlet/Hello进行访问,开始输出日志:

      

      

      

    打开Tomcat 的应用管理界面:localhost:8080/manager/html,找到 HelloServlet

      

      

      

    点击Undeploy,destroy() 方法就会被调用

      

      

      

    日志中输出了destroy() 方法中的日志

      

      

      

    destroy() 方法中可以执行资源释放、日志记录的操作,

    这是 destroy() 方法的最大作用

      

      

      

      

      

      

    【made by siwuxie095】

    转载请注明原文地址: https://ju.6miu.com/read-665113.html

    最新回复(0)