• Servlet的生命周期


    Servlet的生命周期从创建到销毁可分为如下四个过程:

    1. Servlet实例化;
    2. 调用init()方法初始化;
    3. 调用service()方法来处理客户端的请求;
    4. 调用destory()方法销毁;

    接下来我们详细了解下Servlet生命周期的四个过程。

    一、实例化

            根据Servlet请求的路径,查找Servlet的实例,如果实例不存在,则通过调用构造方法完成Servlet实例的创建。Servlet的请求路径可通过配置web.xml文件或者注解的方式,一般都使用注解,比较方便例如(@WebServlet("/demo.do"));

    二、初始化

            通过Servlet实例调用init()方法初始化,init()方法只能调用一次,在第一次创建Servlet时被调用,在之后每次请求时则不再调用。在init()方法里面创建的数据,可以被用于Servlet的整个生命周期。

    代码举例:

    1. package com.my.web.servlet;
    2. import java.io.IOException;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.annotation.WebServlet;
    5. import javax.servlet.http.HttpServlet;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. @WebServlet("/demo.do")
    9. public class DemoServlet extends HttpServlet {
    10. //1.实例化
    11. //构造方法
    12. public DemoServlet() {
    13. System.out.println("DemoServlet被实例化!");
    14. }
    15. //2.初始化
    16. //重写HttpServlet(父类)的init()方法初始化
    17. //通过创建的实例自动调用init()方法
    18. @Override
    19. public void init() throws ServletException {
    20. System.out.println("DemoServlet被初始化!");
    21. }
    22. //3.服务
    23. //通过实例调用父类的Service()方法
    24. //Service()方法会根据请求方式的不同(GET或POST)
    25. //调用子类重写的doGet或doPost方法
    26. //如果子类没有重写,则调用父类的方法(响应405)
    27. // 根据响应方式的不同,需要调用不同的请求方法
    28. @Override
    29. protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    30. System.out.println("service方法被调用!");
    31. }

    3be296b5ef354450ae8014b62625dca7.png

     

            当浏览器请求该Servlet路径时,先通过构造方法创建实例,在通过实例调用init()方法进行初始化,这里浏览器发起了6次请求,可以发现init()方法只被调用了一次。

     

    三、服务

            service()方法是执行实际任务的主要方法。Servlet容器调用service()方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。

            每次服务器接收到一个Servlet请求时,实例化Servlet后,通过实例调用父类的Service()方法,Service()方法会根据请求方式的不同(GET或POST),调用子类重写的doGet()doPost()方法,如果子类没有重写,则调用父类的方法doGet()或doPost()方法,而父类的doGet()和doPost()方法响应一个405错误页面,所以一般都会重写doGet()和doPost()方法。当然,你也可以重写父类的Service方法,但没有实际意义。

    父类HttpServlet中源码如下:

    aaf1e8dc795a47e380ae428c1be998c9.png 

     72266c0bde684b0b81432bda6941d9c2.png

     5bc536f850b84799a9a79c0192c04c02.png

     819af3926dd646818ec4356b05d31a1b.png

     根据响应方式的不同,需要调用不同的请求方法

    代码演示:

    1. package com.my.web.servlet;
    2. import java.io.IOException;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.annotation.WebServlet;
    5. import javax.servlet.http.HttpServlet;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. @WebServlet("/demo.do")
    9. public class DemoServlet extends HttpServlet {
    10. //1.实例化
    11. //构造方法
    12. public DemoServlet() {
    13. System.out.println("DemoServlet被实例化!");
    14. }
    15. //2.初始化
    16. //重写HttpServlet(父类)的init()方法初始化
    17. //通过创建的实例自动调用init()方法
    18. @Override
    19. public void init() throws ServletException {
    20. System.out.println("DemoServlet被初始化!");
    21. }
    22. //3.服务
    23. //通过实例调用父类的Service()方法
    24. //Service()方法会根据请求方式的不同(GET或POST)
    25. //调用子类重写的doGet或doPost方法
    26. //如果子类没有重写,则调用父类的方法(响应405)
    27. // 根据响应方式的不同,需要调用不同的请求方法
    28. // @Override
    29. // protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    30. // System.out.println("doGet方法被调用!");
    31. // }
    32. // @Override
    33. // protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    34. // System.out.println("doPost方法被调用!");
    35. // }

            子类中没有重写父类的doGet()和doPost()方法时,收到来自浏览器的GET请求,则会出现405错误页面。405状态码:代表请求的方式服务器不提供支持

    36601db2213d4cd2bd30b08cdbbe3b4e.png

     b8f4686e25034faaa8b858f7222925ad.png

             子类重写doGet()方法,收到来自浏览器的GET请求,则会通过父类service()方法进行逻辑判断后调用子类重写的doGet()方法。这里我将结果输出至控制台。

            9eb3729a7fbd4f029dd602d4eef761ce.png

     

    四、销毁

            服务器关闭或重启的时候,会调用Servlet实例的destroy()销毁所有的Servlet实例。destroy()方法也只会被调用一次,在Servlet生命周期结束时调用。destroy()方法会将Servlet关闭数据库连接、停止后台线程、把Cookie列表或点击计数器写入到磁盘,并执行其他类似的清理活动。在调用destroy()方法之后,Servlet对象会被标记为垃圾回收。

    代码示例:

    1. package com.my.web.servlet;
    2. import java.io.IOException;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.annotation.WebServlet;
    5. import javax.servlet.http.HttpServlet;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. @WebServlet("/demo.do")
    9. public class DemoServlet extends HttpServlet {
    10. //1.实例化
    11. //构造方法
    12. public DemoServlet() {
    13. System.out.println("DemoServlet被实例化!");
    14. }
    15. //2.初始化
    16. //重写HttpServlet(父类)的init()方法初始化
    17. //通过创建的实例自动调用init()方法
    18. @Override
    19. public void init() throws ServletException {
    20. System.out.println("DemoServlet被初始化!");
    21. }
    22. //3.服务
    23. //通过实例调用父类的Service()方法
    24. //Service()方法会根据请求方式的不同(GET或POST)
    25. //调用子类重写的doGet或doPost方法
    26. //如果子类没有重写,则调用父类的方法(响应405)
    27. // 根据响应方式的不同,需要调用不同的请求方法
    28. // @Override
    29. // protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    30. // System.out.println("service方法被调用!");
    31. // }
    32. @Override
    33. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    34. System.out.println("doGet方法被调用!");
    35. }
    36. // @Override
    37. // protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    38. // System.out.println("doPost方法被调用!");
    39. // }
    40. //销毁
    41. //重写父类的destroy()方法
    42. @Override
    43. public void destroy() {
    44. System.out.println("实例对象已被销毁!");
    45. }
    46. }

            通过浏览器请求Servlet路径发起请求,这里我发送了三次,最后关闭tomcat服务器。

    运行结果

    a5554eb9faa24ac4a6c189e40f0f468e.png

     


    总结:

            当用调用一个Servlet时,就会创建一个Servlet实例,通过实例调用init()方法初始化,可以将Servlet中一直用到的资源放在init()方法中。当客户端(浏览器)请求Servlet路径发起请求,通过请求方式的不同,执行doGet()或doPost()方法,子类中重写doGet()或doPost()方法请求和响应给客户端浏览器。当服务器关闭或重启时,通过实例调用distroy()方法销毁所有Servlet实例,Servlet的生命周期到此就结束了。

     

  • 相关阅读:
    3A通过pmp有多大比例?
    Git详解
    [附源码]计算机毕业设计JAVAjsp旅游景点管理系统
    [附源码]Python计算机毕业设计Django旅游网的设计与实现
    描述Java中的备忘录模式。
    version GLIBC 2.14 not found问题处理
    SpringBoot进阶教程(七十四)整合ELK
    异步编程 - 11 Spring WebFlux的异步非阻塞处理
    python ⾯向对象
    《Effective C++》知识点(1)--让自己习惯C++
  • 原文地址:https://blog.csdn.net/qq_52223733/article/details/126451552