Servlet的生命周期

Servlet是JavaEE提供给我们来处理TCP连接,解析HTTP协议这些底层工作的,我们使用Servlet API编写自己的Servlet来处理HTTP请求,Web服务器实现Servlet API接口,实现底层功能,我们只需要把自己的应用程序跑在Web服务器上。

一个Servlet总是继承自HttpServlet,然后覆写doGet()或doPost()方法。但是不管是doGet还是doPost,它们传入的参数都是HttpServletRequest和HttpServletResponse两个对象,分别代表HTTP请求和响应。这两个对象为我们封装好了请求和响应,我们可以直接使用它们来执行相应的操作即可。

而这样的一个项目最终会打包成一个*.war文件,想要运行这个文件,就需要使用支持ServletAPI的Web容器(Web服务器)。

因此,我们首先要找一个支持Servlet API的Web服务器。常用的服务器有:

  • Tomcat:由Apache开发的开源免费服务器;
  • Jetty:由Eclipse开发的开源免费服务器;
  • GlassFish:一个开源的全功能JavaEE服务器。

 这里我们选择使用最广泛的开源免费的Tomcat服务器。Tomcat服务器实际上就是一个提供Servlet运行的容器,在这个容器中运行的Servlet有以下特点:

  • 无法在代码中直接通过new创建Servlet实例,必须由Servlet容器自动创建Servlet实例;
  • Servlet容器只会给每个Servlet类创建唯一实例;
  • Servlet容器会使用多线程执行doGet()doPost()方法。

一个Web App就是由一个或多个Servlet组成的,每个Servlet通过注解说明自己能处理的路径。一个Webapp完全可以有多个Servlet,分别映射不同的路径。 

注意:早期的Servlet需要在web.xml中配置映射路径,但最新Servlet版本只需要通过注解就可以完成映射。

客户端浏览器在通过一个URL路径发起对一个Servlet请求的过程中,其本质是在调用执行Servlet实例的doXXX()方法。该Servlet实例创建和使用的过程,被称为Servlet的生命周期。整个生命周期共有四个部分,分别是:实例化、初始化、服务、销毁。

  1. 实例化:根据Servlet请求的路径,Tomcat服务器会查找该Servlet实例。如果该实例不存在,则通过调用无参构造方法,完成Servlet实例的创建,该实例只会在第一次请求该Servlet时创建,在没有销毁此实例之前,所有对该Servlet的请求都会反复使用此实例,也就是说,Servlet实例只会在第一次请求的时候创建
  2. 初始化:通过该Servlet实例,调用init()方法,执行初始化的逻辑,我们如果要在执行Servlet之前进行一些操作,都可以在初始化时完成。
  3. 服务:通过该Servlet实例,调用service()方法,如果子类没有重写该方法,则调用HttpServlet父类的service()方法,在父类的该方法中进行请求方式的判断,如果是GET请求,则调用doGet()方法,若子类没有重写该方法,则会调用父类的doGet()方法,而父类的doGet()方法只会报出一个405状态码的错误页面;如果是POST请求,则调用doPost()方法,和doGet()方法一样,若子类没有重写该方法,父类的doPost()方法也会报出一个405状态码的错误页面。
 protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        String method = req.getMethod();

        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);

        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);

        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);

        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);

        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);

        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);

 405状态码:代表请求的方式服务器不提供支持。

底层代码如下:

HttpServlet的doGet()方法:

  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String msg = lStrings.getString("http.method_get_not_supported");
        sendMethodNotAllowed(req, resp, msg);
    }

HttpServlet的doPost()方法: 

 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        String msg = lStrings.getString("http.method_post_not_supported");
        sendMethodNotAllowed(req, resp, msg);
    }

4.销毁:服务器关闭或重启时,会销毁所有的Servlet实例,会调用Servlet实例的destroy()方法,如果你想在销毁Servlet实例时做一些操作,就可以重写父类HttpServlet的destroy()方法,否则,Servlet实例会调用父类的destroy()方法。

Servlet生命周期的具体流程如下图所示:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值