Servlet 的生命周期与工作原理

servlet 通常被称为服务器端小程序,是运行在服务器端的程序,用于处理及相应客户端的请求。

Servlet 的生命周期

当 Servlet 在 Web 容器中运行时,其实例的创建及销毁等都不是由我们程序员决定的,而是由 Web 容器进行控制的。

创建 Servlet 实例有两个时机:
:① 客户端第一次请求某个 Servlet 时系统创建该 Servlet 实例(大部分都是该方式)。
② Web 应用启动时立即创建 Servlet 实例, 即设定 load-on-startup,该属性接收一个整型值,该值越小优先级越高。

Servlet 生命周期可被定义为从创建到毁灭的整个过程:
① Servlet 通过调用 init() 方法进行初始化。
② Servlet 调用 service() 方法来处理客户端的请求。
③ Servlet 通过调用 destroy() 方法终止。
④ 最后,Servlet 被 JVM 垃圾回收器回收。

1、init() 方法
init() 在 Servlet 的整个生命周期中被设计成只调用一次,第一次创建 Servlet 时被调用,后续每次用户请求不再调用。它是在服务器装入 Servlet 时执行,当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交 doGet 或 doPost 方法。 init() 方法简单的创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。通常无需重写该方法,除非在初始化 Servlet 时要完成某些资源的初始化操作。

如果重写了 init(ServletConfig config) 方法,则应在重写该方法的第一行调用 super.init(config)。该方法将调用 HttpServlet 的 init 方法。

public void init() throws ServletException {
    super.init();
    System.out.println("init......");
}

public void init(ServletConfig config) throws ServletException {
    super.init(config);
    System.out.println("TestServlet init......");
}

2、service() 方法
service() 是执行实际任务的主要方法,是 Servlet 的核心,该方法用于生成对客户端的响应。 Servlet 容器(即 Web 容器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。

service() 方法检查 HTTP 请求类型(GET,POST, PUT, DELETE 等),默认的服务功能是调用与 HTTP 请求的方法相对应的 doGet, doPost, doPut, doDelete 等方法。

@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    super.service(req, resp);
}

service() 方法由容器调用,我们不用对 service() 方法做任何的动作,只需要根据请求类型来重载 doGet() 或 doPost() 就行。

3、doGet() 和 doPost() 方法
我们可以根据请求的类型在该方法体内部实现我们的代码。

4、destroy() 方法
destroy() 方法只会被调用一次,即 Servlet 生命周期结束时被调用,即在服务器停止且卸载 Servlet 时执行该方法,通常无需重写该方法。destroy() 方法可以用来释放占用的资源,如数据库连接关闭、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。

destroy() 执行之后, Servlet 对象被标记为垃圾回收。

@Override
public void destroy() {
    super.destroy();
}

5、Servlet 生命流程的大致流程图
这里写图片描述

Servlet 的工作原理

1、Servlet 解析客户端 http 请求流程图
这里写图片描述

步骤:
① web 客户向 Servlet 容器发出 HTTP 请求。
② Servlet 容器解析 web 的 HTTP 请求。
③ Servlet 容器创建一个 HttpServletRequest 对象,在这个对象中封装了 HTTP 请求信息。
④ Servlet 容器创建一个 HttpServletResponse 对象。
⑤ Servlet 容器调用 HttpServlet 的 service() 方法,把 HttpRequest 和 HttpResponse 对象作为 service() 方法的参数传给 HttpServlet 对象。
⑥ HttpServlet 调用 HttpRequest 的相关方法获取 HTTP 请求信息。
⑦ HttpServlet 调用 HttpResponse 的相关方法生成相应数据。
⑧ Servlet 容器把 HttpServlet 的响应结果返回 web 用户。

2、工作原理解析:

① 接收和响应客户请求:客户端先向 Servlet 容器发送一个请求,Servlet 调用 service() 方法进行响应,service() 方法对请求的方式进行匹配,选择相应的 do 方法,然后再进入对应的方法中调用逻辑层的方法,实现对客户端的响应。源码如下:

if(method.equals("GET")) {
    errMsg = this.getLastModified(req);
    if(errMsg == -1L) {
        this.doGet(req, resp);
    } else {
        long ifModifiedSince = req.getDateHeader("If-Modified-Since");
        if(ifModifiedSince < errMsg) {
            this.maybeSetLastModified(resp, errMsg);
            this.doGet(req, resp);
        } else {
            resp.setStatus(304);
        }
    }
} else if(method.equals("HEAD")) {
    errMsg = this.getLastModified(req);
    this.maybeSetLastModified(resp, errMsg);
    this.doHead(req, resp);
} else if(method.equals("POST")) {
    this.doPost(req, resp);
} else if(method.equals("PUT")) {
    this.doPut(req, resp);
} else if(method.equals("DELETE")) {
    this.doDelete(req, resp);
} else if(method.equals("OPTIONS")) {
    this.doOptions(req, resp);
} else if(method.equals("TRACE")) {
    this.doTrace(req, resp);
} else {
    String errMsg1 = lStrings.getString("http.method_not_implemented");
    Object[] errArgs = new Object[]{method};
    errMsg1 = MessageFormat.format(errMsg1, errArgs);
    resp.sendError(501, errMsg1);
}

② GenericServlet 是一个通用的,不特定于任何协议的 Servlet ,它实现了 Servlet 接口, 而 HttpServlet 继承于 GenericServlet,因此 HttpServlet 也实现了 Servlet 接口,我们在自定义 Servlet 接口时只需要继承 HttpServlet 接口就行。

③ Servlet 接口和 GenericServlet 是不特定于任何协议的, 而 HttpServlet 是特定于 HTTP 协议的类, 所以HttpServlet中实现了service()方法,并将请求ServletRequest、ServletResponse 强转为HttpRequest 和 HttpResponse。HttpServlet 中的源码如下:

if(req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
    HttpServletRequest request = (HttpServletRequest)req;
    HttpServletResponse response = (HttpServletResponse)res;
    this.service(request, response);
} else {
    throw new ServletException("non-HTTP request or response");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值