1、什么是Servlet对象生命周期?

  • Servlet对象是什么时候被创建?
  • Servlet对象是什么时候被销毁?
  • Servlet对象创建了几个?
  • Servlet对象的生命周期表示:一个Servlet对象从出生到最后的死亡,整个过程是怎样的?
  • Servlet对象是由谁来维护的?

    2、Servlet对象生命周期

    2.1 Servlet对象和WEB容器

  • Servlet对象的创建,对象上方法的调用,对象最终的销毁,程序员是无权干预的

  • Servlet对象的生命周期是由Tomcat服务器(WEB Sever)全权负责的
  • Tomcat服务器通常我们又称为:WEB容器
  • 我们自己new的Servlet对象是不受WEB容器管理的
  • WEB容器创建的Servlet对象,这些是Servlet对象都会被放到一个集合当中(HashMap),只有放到这个HashMap集合中的Servlet才能够被WEB容器管理,自己new的Servlet的对象不会被WEB容器管理,(自己new的Servlet独享不在容器当中)
  • WEB容器底层应该都有一个HashMap这样的集合,在这个集合当中存储了Servlet对象和请求路径之间的关系

    2.2 Servlet对象生命周期

    ```java package servlet;

import jakarta.servlet.*;

import java.io.IOException;

/**

  • @Author: 小雷学长
  • @Date: 2022/3/17 - 10:37
  • @Version: 1.8 */ public class AServlet implements Servlet {

    //无参数构造方法 public AServlet() {

    1. System.out.println("A无参数构造方法启动了");

    }

    @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    1. System.out.println("A service启动了");

    }

    @Override public void destroy() {

    1. System.out.println("A destory启动了");

    }

    @Override public void init(ServletConfig servletConfig) throws ServletException {

    1. System.out.println("A inti启动了");

    }

    @Override public String getServletInfo() {

    1. return null;

    }

    @Override public ServletConfig getServletConfig() {

    1. return null;

    }

}

  1. - 默认情况下服务器启动时 A Servlet对象并没有被实例化
  2. - 用户发送第一次请求的时候,控制台输出了以下内容:

A无参数构造方法启动了 A inti启动了 A service启动了

  1. - 根据以上输出的内容得出结论:
  2. 1. 用户在发送第一次请求的时候Servlet对象被实例化(AServlet构造的方法被执行了。并且执行的是无参数构造方法)
  3. 1. A Servlet对象被创建出来之后,Tomcat服务器马上调用了AServlet对象的init方法(init方法在执行的时候,Servlet对象已经存在了,已经被创建出来了)
  4. 1. 无参数构造方法、init方法只在第一次用户发送请求的时候执行,也就是说无参数构造方法只执行一次,init方法只被Tomcat服务器调用一次
  5. 1. 只要用户发送一次请求,service方法必然只会被Tomcat定位器调用一次,发送100次请求,service方法会被调用100
  6. 1. 关闭服务器的时候,控制台输出了以下内容

A destory启动了

  1. - 通过以上输出内容,可以得出一下结论:
  2. - Servletdestroy方法只被Tomcat服务器用一次
  3. - destroy方法在服务器关闭的时候被调用,因为服务器关闭的时候要销毁AServlet对象的内存
  4. - 服务器在销毁A Servlet对象内存之前,Tomcat服务器会自动调用AServlet对象的destroy方法
  5. - destroy方法执行的时候A Servlet对象还在,没有被销毁,destroy方法执行结束之后,AServlet对象的内存才会被释放
  6. <a name="SrIpx"></a>
  7. ## 2.3 Servlet生命周期总结
  8. <a name="nliNz"></a>
  9. ### 2.3.1 各方法的含义
  10. - 无参数构造方法执行:标志着出生
  11. - init方法的执行:标志着正在接收教育
  12. - service方法的执行:标志着开始工作,并且一直服务
  13. - destroy方法的执行:标志着临终
  14. <a name="UH4Fl"></a>
  15. ### 2.3.2 各方法被调用的次数
  16. - 构造方法只执行一次
  17. - init方法只执行一次
  18. - service方法:用户发送一次请求一次,发送N次请求N
  19. - destroy方法只执行一次
  20. <a name="wVrA6"></a>
  21. ### 2.3.3 常见错误
  22. - Servlet类中编写一个有参数构造方法,如果没有手动编写无参数构造方法会报错,`500错误---->500错误是一个HTTP协议的错误状态码`,一般情况下是因为服务器端的Java程序出现了异常(服务器内部错误都是500错误)
  23. ```java
  24. /* //无参数构造方法
  25. public AServlet() {
  26. System.out.println("A无参数构造方法启动了");
  27. }*/
  28. //程序员手动提供有参数的构造方法
  29. public AServlet(String s){
  30. }

image.png

  • 如果没有无参数的构造方法会导致500错误
  • 一般不建议程序员来定义构造方法

    3、研究

    ```java package servlet;

import jakarta.servlet.*;

import java.io.IOException;

/**

  • @Author: 小雷学长
  • @Date: 2022/3/17 - 10:37
  • @Version: 1.8 */ public class AServlet implements Servlet {

    //无参数构造方法 public AServlet(){

    1. System.out.println("无参数构造方法");

    } @Override public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override public ServletConfig getServletConfig() {

    1. return null;

    }

    @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

    @Override public String getServletInfo() {

    1. return null;

    }

    @Override public void destroy() {

    } }

  1. ```java
  2. package servlet;
  3. import jakarta.servlet.*;
  4. import java.io.IOException;
  5. /**
  6. * @Author: 小雷学长
  7. * @Date: 2022/3/17 - 11:03
  8. * @Version: 1.8
  9. */
  10. public class BServlet implements Servlet {
  11. //无参数构造方法
  12. public BServlet() {
  13. System.out.println("这是B无参数构造");
  14. }
  15. @Override
  16. public void init(ServletConfig servletConfig) throws ServletException {
  17. }
  18. @Override
  19. public ServletConfig getServletConfig() {
  20. return null;
  21. }
  22. @Override
  23. public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
  24. }
  25. @Override
  26. public String getServletInfo() {
  27. return null;
  28. }
  29. @Override
  30. public void destroy() {
  31. }
  32. }
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  5. version="4.0">
  6. <servlet>
  7. <servlet-name>aservlet</servlet-name>
  8. <servlet-class>servlet.AServlet</servlet-class>
  9. </servlet>
  10. <servlet-mapping>
  11. <servlet-name>aservlet</servlet-name>
  12. <url-pattern>/a</url-pattern>
  13. </servlet-mapping>
  14. <servlet>
  15. <servlet-name>bservlet</servlet-name>
  16. <servlet-class>servlet.BServlet</servlet-class>
  17. </servlet>
  18. <servlet-mapping>
  19. <servlet-name>bservlet</servlet-name>
  20. <url-pattern>/b</url-pattern>
  21. </servlet-mapping>
  22. </web-app>
  1. 测试发现,服务器在启动时Servlet对象不会被实例化
  2. 这个设计是合理的,用户没有发送请求之前,如果提前创建出来所有的Servlet对象,必然是消耗内存的,并且一直没有用用户访问,显然这个Servlet对象是一个废物,没必要先创建

    3.1 如何让服务器启动的时候创建Servlet对象

  3. 在Servlet标签中添加_<_load-on-startup_>_0_</_load-on-startup_>_子标签,在该子标签中,越小的整数优先级越高

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    5. version="4.0">
    6. <servlet>
    7. <servlet-name>aservlet</servlet-name>
    8. <servlet-class>servlet.AServlet</servlet-class>
    9. <load-on-startup>0</load-on-startup>
    10. </servlet>
    11. <servlet-mapping>
    12. <servlet-name>aservlet</servlet-name>
    13. <url-pattern>/a</url-pattern>
    14. </servlet-mapping>
    15. <servlet>
    16. <servlet-name>bservlet</servlet-name>
    17. <servlet-class>servlet.BServlet</servlet-class>
    18. <load-on-startup>1</load-on-startup>
    19. </servlet>
    20. <servlet-mapping>
    21. <servlet-name>bservlet</servlet-name>
    22. <url-pattern>/b</url-pattern>
    23. </servlet-mapping>
    24. </web-app>

    image.png

  4. 一般不配,特殊情况下才配

    4、各方法的使用

    4.1 service方法

  • [x] service方法是使用最多的方法,service方法一定要实现的,因为service方法是处理用户请求的核心方法

    4.2 init方法

  • [x] init方法很少用,通常在init方法中当初始化操作,并且这个初始化操作只需要执行一次,例如:数据库连接池,初始化线程池……

    4.3 destroy方法

  • [x] destroy方法也很少用,通常在destroy方法中,进行资源的关闭,马上对象要被销毁时,抓紧时间关闭资源,还有什么资源没保存的,抓紧时间保存一下

    4.4 无参数构造方法能不能代替init方法?

  • [x] 不能。

  • Servlet规范中要求,作为Javaweb程序员,编写Servlet类的时候,不建议手动编写构造方法,很容易让无参数构造方法消失,这个操作可能会导致Servlet对象无法实例化。
  • 所以init方法的存在是必要的