• [03] Servlet继承关系和生命周期



    1、Servlet的继承关系

    假如现有我们自定义的一个Servlet,继承HttpServlet,那么实际上它的继承链如下图:
     
    可以看到,核心的部分在于:
    • 两个顶级接口
      • Servlet
      • ServletConfig
    • 接口的实现类
      • GenericServlet
    • 基于HTTP协议的实现类
      • HttpServlet

    我们剥离一下,把不需要看的去掉,再把方法显示一下,可清晰知道Servlet的整体继承关系如下

     其中重点摘录部分进行说明:

    • ServletConfig  Servlet的配置信息,常用来在Servlet初始化时进行信息传递
      • getServletContext()  获取Servlet运行的上下文环境对象,可以获取对应信息(如Servlet路径),存取容量级的变量
      • getInitParameter(String name)  获取初始化参数(web.xml中配置的init-param)

    • GenericServlet  一般的Servlet,实现了Servlet和ServletConfig接口
      • init(ServletConfig config)  初始化方法,方法中调用了init()
      • init()  初始化方法,方法体为空,主要用于自定义Servlet的覆盖
      • service(ServletRequest request, ServletResponse response)  抽象方法service,要求继承类实现
      • destory()  Servlet销毁前要执行的方法

    • HttpServlet  基于HTTP协议的实现类
      • service(ServletRequest request, ServletResponse response) 实现了GenericServlet的抽象方法,调用了service(HttpServletRequest, HttpServletResponse)
      • service(HttpServletRequest request, HttpServletResponse response)  根据请求的不同调用了doGet或doPost方法
      • doGet()  处理GET方式的请求
      • doPost()  处理POST方式的请求

    其中稍微提一下,在GenericServlet中有个init(ServletConfig config)方法,调用了init()方法,但是init()方法体却为空,为什么?

    public void init(ServletConfig config) throws ServletException { 
        this.config = config;
        this.init();
    }
    public void init() throws ServletException {
    
    }

    首先,为了方便能够在其他地方也能直接使用ServletConfig对象,而不仅仅局限在init(ServletConfig config)方法中,所以创建一个私有的成员变量config,在init(ServletConfig config)方法中就将其赋值给config,这样一来,GenericServlet和其子类都可以调用其getServletConfig()方法来获取ServletConfig对象了。

    之所以有空的init(),实际上就是为了后续的扩展和重写,有需要的情况下去覆盖init()而不是去覆盖init(ServletConfig config),因为后者一旦覆盖,就无法通过上述的方法在其他地方便捷地调用getServletConfig方法获取ServletConfig对象了。

    实际上,Servlet继承关系文字描述起来反而复杂,结合继承图和源码查看,能更加清晰明了,这里进行了大概的阐述,更多细节的话需要查看源码或者API了,此处不再详细展开。

    2、Servlet的生命周期

    Servlet之间的启动是有先后顺序的,这可以在web.xml中通过<load-on-startup>标签进行设定,参数为数字,表示了启动的顺序。启动顺序的默认值是0:
    • load-on-startup --> 0:Servlet被访问时才进行实例化
    • load-on-startup --> other:在容器启动时进行Servlet实例化

    即是说,默认不配置该参数的情况下,Servlet只有再被访问时才会实例化;配置了参数以后,根据参数按顺序在容器启动时就将Servlet实例化

    然后,Servlet的生命周期,其实说来也简单:
    • 容器在加载Servlet的时候,会执行其init()方法
    • 当接收请求的时候,会调用service(ServletReqeust request, ServletResponse response)方法,继而调用doGet或doPost方法
    • 在服务器关闭之前,会调用Servlet的destory()方法

    即:
    • init()
    • doGet() / doPost()
    • destory()

    实际上,完整一点来说:
    • 初始化
      • 构造方法
      • init(ServletConfig config)
      • init()
    • 提供服务
      • service(ServletRequest request, ServletResponse response)
      • doGet() / doPost()
    • 销毁
      • destory()

    (写得有点啰嗦...)
     
    最后简单总结下要点:
    • Servlet只初始化一次,它是单例的,只有一个实例,通过多线程访问。即Servlet是多线程单实例的
    • 实例化过程中,先调用构造方法,再调用init方法,所以初始化操作可以覆盖写到init方法中
    • 请求方式不同会调用doGet()或doPost()方法
    • 根据实际情况在Servlet销毁前调用其destroy()方法
     

  • 相关阅读:
    负载均衡的部署方式
    nginx 负载均衡相关知识
    nginx 的模块及处理流程
    win7 下配置resin的一些tip
    Eclipse插件安装的三种方法
    win 7 下Maven环境的搭建
    Effective C++ 第二版 17)operator=检查自己 18)接口完整 19)成员和友元函数
    网络子系统54_ip协议分片重组_定位ipq
    HDU 1796How many integers can you find(简单容斥定理)
    如何关闭dell inspiron n4010的内置麦克
  • 原文地址:https://www.cnblogs.com/deng-cc/p/7462866.html
Copyright © 2020-2023  润新知