Servlet处理流程分析

来源:互联网 发布:下载哈萨克dombira软件 编辑:程序博客网 时间:2024/06/06 18:01

---------------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/javaeehttp://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】

0 0
原创粉丝点击