JavaWeb开发底子Servlet生命周期与工作原理

[复制链接]
发表于 2025-7-9 02:05:53 | 显示全部楼层 |阅读模式
Servlet生命周期

  Servlet的生命周期由Servlet容器(如Tomcat、Jetty等)管理,主要包罗以下5个阶段:
  

  • 加载Servlet类
  • 创建Servlet实例
  • 调用init方法
  • 调用service方法
  • 调用destroy方法
  

  

  • 加载(Loading):

    • 当Servlet容器启动或第一次吸收到对某个Servlet的请求时,它会加载Servlet类
    • 这个过程只发生一次,除非Servlet被卸载或容器重新启动

  • 实例化(Instantiation):

    • 在加载Servlet类之后,容器会创建一个Servlet实例
    • 这个实例化过程也是一次性的,除非Servlet被卸载或容器重新启动

  • 初始化(Initialization):

    • 容器调用Servlet实例的init()方法进行初始化
    • init()方法只被调用一次,用于执行一次性的初始化任务,如读取设置参数、初始化资源等
    • 你可以重写init()方法以执行自界说的初始化逻辑
      1. public void init(ServletConfig config)
      复制代码

  • 请求处理(Request Handling):

    • 每当有请求到达时,容器会调用Servlet的service()方法来处理请求
    • service()方法根据请求的范例(如GET、POST等)调用相应的处理方法(如doGet()、doPost()等)
      1. public void service(ServletRequest request, ServletResponse response)
      复制代码

  • 销毁(Destruction):

    • 当容器决定卸载Servlet(如容器关闭或Servlet被重新加载)时,它会调用Servlet的destroy()方法
    • destroy()方法用于执行清理任务,如关闭资源、生存状态等
    • destroy()方法只被调用一次
      1. public void destroy()
      复制代码

  Servlet重新加载
  Servlet被重新加载通常发生在以下几种环境下:
  

  • Servlet类文件被修改:

    • 假如在开发过程中修改了Servlet类文件,Servlet容器大概会检测到这些更改并重新加载Servlet
    • 这通常发生在开发环境中,生产环境中一般不会主动重新加载

  • 容器设置发生变化:

    • 假如修改了Servlet容器的设置文件(如web.xml),容器大概会重新加载相关的Servlet

  • 容器重启:

    • 当Servlet容器重启时,所有的Servlet都会被重新加载

  • 手动重新加载:

    • 某些Servlet容器提供了手动重新加载Servlet的功能,通常通过管理控制台或命令行工具

  当Servlet被重新加载时,Servlet容器会执行以下步骤:
  

  • 销毁现有的Servlet实例:

    • 容器调用现有Servlet实例的destroy()方法,执行清理任务
    • 开释资源,如关闭数据库连接、开释文件句柄等

  • 卸载Servlet类:

    • 容器卸载现有的Servlet类,开释类加载器持有的资源

  • 重新加载Servlet类:

    • 容器重新加载Servlet类文件,创建新的类加载器实例

  • 实例化新的Servlet对象:

    • 容器创建新的Servlet实例

  • 初始化新的Servlet实例:

    • 容器调用新的Servlet实例的init()方法进行初始化

  Servlet代码示例

  有3种方式使用Servlet:
  ①实现Servlet接口
  1. import java.io.*;
  2. import javax.servlet.*;
  3. public class First implements Servlet {
  4.     ServletConfig config = null;
  5.     public void init(ServletConfig config) {
  6.         this.config = config;
  7.         System.out.println("servlet is initialized");
  8.     }
  9.     public void service(ServletRequest req, ServletResponse res)
  10.             throws IOException, ServletException {
  11.         res.setContentType("text/html");
  12.         PrintWriter out = res.getWriter();
  13.         out.print("<html><body>");
  14.         out.print("<b>hello simple servlet</b>");
  15.         out.print("</body></html>");
  16.     }
  17.     public void destroy() {
  18.         System.out.println("servlet is destroyed");
  19.     }
  20.     public ServletConfig getServletConfig() {
  21.         return config;
  22.     }
  23.     public String getServletInfo() {
  24.         return "copyright 2007-1010";
  25.     }
  26. }
复制代码
②继承GenericServlet类
  1. import java.io.*;
  2. import javax.servlet.*;
  3. public class First extends GenericServlet {
  4.     public void service(ServletRequest req, ServletResponse res)
  5.             throws IOException, ServletException {
  6.         res.setContentType("text/html");
  7.         PrintWriter out = res.getWriter();
  8.         out.print("<html><body>");
  9.         out.print("<b>hello generic servlet</b>");
  10.         out.print("</body></html>");
  11.     }
  12. }
复制代码
③继承HttpServlet类
  1. import javax.servlet.http.*;
  2. import javax.servlet.*;
  3. import java.io.*;
  4. public class DemoServ extends HttpServlet {
  5.     public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
  6.         res.setContentType("text/html");
  7.         PrintWriter pw = res.getWriter();
  8.         String name = req.getParameter("name");
  9.         pw.println("Welcome " + name);
  10.     }
  11. }
复制代码
继承HttpServlet类是最常用的方式,接下来通过六个步骤,看看具体实践。
  第一步,创建目录结构。
  

  第二步,创建Servlet。
  1. import javax.servlet.http.*;
  2. import javax.servlet.*;
  3. import java.io.*;
  4. public class DemoServlet extends HttpServlet {
  5.     public void doGet(HttpServletRequest req, HttpServletResponse res)
  6.             throws ServletException, IOException {
  7.         res.setContentType("text/html");
  8.         PrintWriter pw = res.getWriter();
  9.         pw.println("<html><body>");
  10.         pw.println("Welcome to servlet");
  11.         pw.println("</body></html>");
  12.         pw.close();
  13.     }
  14. }
复制代码
第三步,编译Servlet。
  1. <dependency>
  2.     <groupId>javax.servlet</groupId>
  3.     <artifactId>javax.servlet-api</artifactId>
  4.     <version>3.1.0</version>
  5.     <scope>provided</scope>
  6. </dependency>
复制代码
编译后将class文件拷贝到WEB-INF/classes。
  第四步,创建web.xml。
  1. <web-app>
  2.     <servlet>
  3.         <servlet-name>sonoojaiswal</servlet-name>
  4.         <servlet-class>DemoServlet</servlet-class>
  5.     </servlet>
  6.     <servlet-mapping>
  7.         <servlet-name>sonoojaiswal</servlet-name>
  8.         <url-pattern>/welcome</url-pattern>
  9.     </servlet-mapping>
  10. </web-app>
复制代码
web.xml是一个摆设形貌符文件,用于设置Java Web应用步调。
  Java Servlet 3.0引入了@WebServlet注解,用于简化Servlet的设置:
  1. import javax.servlet.http.*;
  2. import javax.servlet.*;
  3. import java.io.*;
  4. import javax.servlet.annotation.WebServlet;
  5. @WebServlet("/welcome")
  6. public class DemoServlet extends HttpServlet {
  7.     private static final long serialVersionUID = 1L;
  8.     public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
  9.         res.setContentType("text/html");
  10.         PrintWriter pw = res.getWriter();
  11.         pw.println("<html><body>");
  12.         pw.println("Welcome to servlet");
  13.         pw.println("</body></html>");
  14.         pw.close();
  15.     }
  16. }
复制代码
    web.xml在低版本Servlet是必须的,在高版本Servlet已经不再必要。
    第五步,摆设Servlet。
  将项目文件复制到Apache Tomcat的webapps目录下,启动Tomcat服务。
  第六步,访问Servlet。
  浏览器请求http://localhost:9999/demo/welcome,就能看到Servlet相应内容。
  Servlet工作原理

  

  • 请求映射:

    • 浏览器发送一个HTTP请求到服务器
    • 服务器根据web.xml文件中的设置,将请求映射到相应的Servlet

  • 创建请求和相应对象:

    • 服务器为每个请求创建HttpServletRequest和HttpServletResponse对象。这些对象包含了请求的所有信息和用于生成相应的方法

  • 调用service方法:

    • 服务器在一个新的线程中调用Servlet的service方法来处理请求

  • 调用public service方法:

    • public service 方法内部会调用protected service方法。public service方法是HttpServlet类的一部分,它负责处理所有范例的HTTP请求
      1. public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
      2.     if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
      3.         HttpServletRequest request = (HttpServletRequest)req;
      4.         HttpServletResponse response = (HttpServletResponse)res;
      5.         this.service(request, response);
      6.     } else {
      7.         throw new ServletException("non-HTTP request or response");
      8.     }
      9. }
      复制代码

  • 调用protected service方法:

    • protected service方法根据请求的范例(如GET、POST等)调用相应的处理方法(如doGet、doPost等)
      1. protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      2.     String method = req.getMethod();
      3.     long lastModified;
      4.     if (method.equals("GET")) {
      5.         lastModified = this.getLastModified(req);
      6.         if (lastModified == -1L) {
      7.             this.doGet(req, resp);
      8.         } else {
      9.             long ifModifiedSince = req.getDateHeader("If-Modified-Since");
      10.             if (ifModifiedSince < lastModified) {
      11.                 this.maybeSetLastModified(resp, lastModified);
      12.                 this.doGet(req, resp);
      13.             } else {
      14.                 resp.setStatus(304);
      15.             }
      16.         }
      17.     } else if (method.equals("HEAD")) {
      18.         lastModified = this.getLastModified(req);
      19.         this.maybeSetLastModified(resp, lastModified);
      20.         this.doHead(req, resp);
      21.     } else if (method.equals("POST")) {
      22.         this.doPost(req, resp);
      23.     } else if (method.equals("PUT")) {
      24.         this.doPut(req, resp);
      25.     } else if (method.equals("DELETE")) {
      26.         this.doDelete(req, resp);
      27.     } else if (method.equals("OPTIONS")) {
      28.         this.doOptions(req, resp);
      29.     } else if (method.equals("TRACE")) {
      30.         this.doTrace(req, resp);
      31.     } else {
      32.         String errMsg = lStrings.getString("http.method_not_implemented");
      33.         Object[] errArgs = new Object[]{method};
      34.         errMsg = MessageFormat.format(errMsg, errArgs);
      35.         resp.sendError(501, errMsg);
      36.     }
      37. }
      复制代码

  • 调用doGet方法:

    • 假如请求范例是GET,protected service方法会调用doGet方法。doGet方法处理请求并生成相应

  • 生成相应并发送给客户端:

    • doGet方法生成相应(如HTML、JSON等),并通过HttpServletResponse对象将相应发送回客户端

  • 删除请求和相应对象:

    • 在相应发送完毕后,Web容器会删除HttpServletRequest和HttpServletResponse对象,以开释资源
    • 处理请求的线程要么被返回到线程池,要么被删除,这取决于服务器的实现

  总结,Servlet的生命周期包罗初始化(init)、请求处理(service,调用doGet、doPost等)、和销毁(destroy)。工作原理是:客户端请求,服务器分发,创建请求和相应对象,调用service方法,生成并发送相应,删除请求和相应对象。
     参考资料:
   https://www.javatpoint.com/life-cycle-of-a-servlet
   https://www.javatpoint.com/steps-to-create-a-servlet-using-tomcat-server
   https://www.javatpoint.com/how-servlet-works
   ChatGPT

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

© 2001-2025 Discuz! Team. Powered by Discuz! X3.5

GMT+8, 2025-7-25 07:41 , Processed in 0.077919 second(s), 30 queries 手机版|qidao123.com技术社区-IT企服评测▪应用市场 ( 浙ICP备20004199 )|网站地图

快速回复 返回顶部 返回列表