Servlet对象的生命周期

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

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

二、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对象生命周期

  1. package servlet;
  2. import jakarta.servlet.*;
  3. import java.io.IOException;
  4. /**
  5. * @Author: 小雷学长
  6. * @Date: 2022/3/17 - 10:37
  7. * @Version: 1.8
  8. */
  9. public class AServlet implements Servlet {
  10. //无参数构造方法
  11. public AServlet() {
  12. System.out.println("A无参数构造方法启动了");
  13. }
  14. @Override
  15. public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
  16. System.out.println("A service启动了");
  17. }
  18. @Override
  19. public void destroy() {
  20. System.out.println("A destory启动了");
  21. }
  22. @Override
  23. public void init(ServletConfig servletConfig) throws ServletException {
  24. System.out.println("A inti启动了");
  25. }
  26. @Override
  27. public String getServletInfo() {
  28. return null;
  29. }
  30. @Override
  31. public ServletConfig getServletConfig() {
  32. return null;
  33. }
  34. }
  • 默认情况下服务器启动时 A Servlet对象并没有被实例化
  • 用户发送第一次请求的时候,控制台输出了以下内容:
  1. A无参数构造方法启动了
  2. A inti启动了
  3. A service启动了
  • 根据以上输出的内容得出结论:

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

    • Servlet的destroy方法只被Tomcat服务器用一次
    • destroy方法在服务器关闭的时候被调用,因为服务器关闭的时候要销毁AServlet对象的内存
    • 服务器在销毁A Servlet对象内存之前,Tomcat服务器会自动调用AServlet对象的destroy方法
    • destroy方法执行的时候A Servlet对象还在,没有被销毁,destroy方法执行结束之后,AServlet对象的内存才会被释放

2.3 Servlet生命周期总结

(1) 各方法的含义

  • 无参数构造方法执行:标志着出生
  • init方法的执行:标志着正在接收教育
  • service方法的执行:标志着开始工作,并且一直服务
  • destroy方法的执行:标志着临终

(2)各方法被调用的次数

  • 构造方法只执行一次
  • init方法只执行一次
  • service方法:用户发送一次请求一次,发送N次请求N次
  • destroy方法只执行一次

(3)常见错误

  • 当Servlet类中编写一个有参数构造方法,如果没有手动编写无参数构造方法会报错,500错误---->500错误是一个HTTP协议的错误状态码,一般情况下是因为服务器端的Java程序出现了异常(服务器内部错误都是500错误)
  1. /* //无参数构造方法
  2. public AServlet() {
  3. System.out.println("A无参数构造方法启动了");
  4. }*/
  5. //程序员手动提供有参数的构造方法
  6. public AServlet(String s){
  7. }

9、Servlet对象的生命周期 - 图1

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

三、研究

  1. package servlet;
  2. import jakarta.servlet.*;
  3. import java.io.IOException;
  4. /**
  5. * @Author: 小雷学长
  6. * @Date: 2022/3/17 - 10:37
  7. * @Version: 1.8
  8. */
  9. public class AServlet implements Servlet {
  10. //无参数构造方法
  11. public AServlet(){
  12. System.out.println("无参数构造方法");
  13. }
  14. @Override
  15. public void init(ServletConfig servletConfig) throws ServletException {
  16. }
  17. @Override
  18. public ServletConfig getServletConfig() {
  19. return null;
  20. }
  21. @Override
  22. public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
  23. }
  24. @Override
  25. public String getServletInfo() {
  26. return null;
  27. }
  28. @Override
  29. public void destroy() {
  30. }
  31. }
  1. package servlet;
  2. import jakarta.servlet.*;
  3. import java.io.IOException;
  4. /**
  5. * @Author: 小雷学长
  6. * @Date: 2022/3/17 - 11:03
  7. * @Version: 1.8
  8. */
  9. public class BServlet implements Servlet {
  10. //无参数构造方法
  11. public BServlet() {
  12. System.out.println("这是B无参数构造");
  13. }
  14. @Override
  15. public void init(ServletConfig servletConfig) throws ServletException {
  16. }
  17. @Override
  18. public ServletConfig getServletConfig() {
  19. return null;
  20. }
  21. @Override
  22. public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
  23. }
  24. @Override
  25. public String getServletInfo() {
  26. return null;
  27. }
  28. @Override
  29. public void destroy() {
  30. }
  31. }
  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对象

  1. 在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>

9、Servlet对象的生命周期 - 图2

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

四、各方法的使用

4.1 service方法

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

4.2 init方法

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

4.3 destroy方法

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

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

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