SpringMvc之Servlet 生命周期、工作原理-yellowcong

我最开始写的是SpringMVC的开始案例,从SpringMvc的请求原理,写着写着,就写到了Servlet的生命周期了,感觉越写越底层啊。主要掌握Servlet的生命周期,以及HttpServler与Servlet的关系

类关系结构

Servlet

Servlet这个类是一个接口,并不是一个实体类,但是这个接口可以说,就是祖师爷了,所有的Servlet服务都实现了它。

servlet的生命周期,就是init ->service ->destroy,可以说就是挺简单的,在JDK中的,Servlet的实现类是GenericServlet
这里写图片描述

GenericServlet

GenericServlet 这个类是一个抽象类,并没有完全的实现Servlet的所有接口,service 这个方法为抽象方法,由子类去实现(这种设计模式被成为模板模式(钩子函数))
这里写图片描述

service方法是抽象方法,大家可以仔细的看我框出来的那个函数,前面有一个 A,表示的是抽象方法

这里写图片描述

HttpServlet

HttpServlet实现了GenericServlet类,但是仍然是抽象类,需要子类去继承HttpServlet,然后复写里面的doGet和doPost方法

这里写图片描述

下图的代码可以看到,虽然是实现了Servlet所有接口,但是并不能直接使用,需要子类去继承HttpServlet
这里写图片描述

service方法与doGet和doPost关系

类/接口关系
javax.servlet.Servlet(接口)定义的接口
javax.servlet.GenericServlet(抽象类)实现Servlet
javax.servlet.http.HttpServlet(抽象类)继承了GenericServlet抽象类

在下代码,大家可以发现,所谓的doGet和doPost方法,都不过是一个钩子函数,大家最后调用的都是service方法,在方法里面判断请求的类型,然后再去调用钩子函数doGet/doPost

protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
    String method = req.getMethod();

    //请求的方法是否是get类型
    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 = req.getDateHeader(HEADER_IFMODSINCE);
            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);
    //是否是post类型
    } 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);

    } else {
        //
        // Note that this means NO servlet supports whatever
        // method was requested, anywhere on this server.
        //

        String errMsg = lStrings.getString("http.method_not_implemented");
        Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } }

ServletRequest/HttpServletRequest

在HttpServlet中的service方法,会将接口定义的ServletRequest 转化为HttpServletRequest,然后调用自己复写的service方法来处理请求。

这里写图片描述

大家看图会发现,其实HttpServletRequest接口继承了ServletRequest接口和HttpServletResponse接口继承了ServletResponse接口

这里写图片描述

这里写图片描述

说实话有人真的很无尿,会问你,HttpServletRequest和ServletRequest的区别,我尼玛想呼死你,这两个接口的关系是继承关系,区别就是HttpServletRequest(子类)拥有更多的http相关处理的方法咯

生命周期

Servlet 生命周期:Servlet 加载—>实例化—>服务—>销毁。

方法执行次数执行时候
init一次1、客户端调用Servlet,2、容器初始化,在web.xml配置load-on-startup,3、容器初始化,配置了init-param
service多次每次客户端访问servlet,都会调用
destroy一次当容器退出时(Tomcat退出)



init(只执行一次,在):在Servlet的生命周期中,仅执行一次init()方法。它是在服务器装入Servlet时执行的,负责初始化Servlet对象。可以配置服务器,以在启动服务器或客户机首次访问Servlet时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行init。

service(执行多次):它是Servlet的核心,负责响应客户的请求。每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的然后去调用doGet和doPost等。

destroy(执行一次,在容器退出(Tomcat关闭)): 仅执行一次,在服务器端停止且卸载Servlet时执行该方法。当Servlet对象退出生命周期时,负责释放占用的资源。一个Servlet在运行service()方法时可能会产生其他的线程,因此需要确认在调用destroy()方法时,这些线程已经终止或完成。

创建Servlet对象的时机

1、Servlet容器启动时:读取web.xml配置文件中的信息,构造指定的Servlet对象,创建ServletConfig对象,同时将ServletConfig对象作为参数来调用Servlet对象的init方法。

2、在Servlet容器启动后:客户首次向Servlet发出请求,Servlet容器会判断内存中是否存在指定的Servlet对象,如果没有则创建它,然后根据客户的请求创建HttpRequest、HttpResponse对象,从而调用Servlet 对象的service方法。

3、Servlet Servlet容器在启动时自动创建Servlet,这是由在web.xml文件中为Servlet设置的属性决定的。从中我们也能看到同一个类型的Servlet对象在Servlet容器中以单例的形式存在。

  <servlet>
          <servlet-name>Init</servlet-name>
          <servlet-class>com.yellowcong.servlet.InitServlet</servlet-class>
          <load-on-startup>1</load-on-startup>
  </servlet>

请求时序图

这里写图片描述

转载于:https://my.oschina.net/u/1987703/blog/1617633

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值