JavaWeb——Servlet生命周期

一、什么是 Servlet 生命周期?

Servlet 生命周期指的是一个 Servlet 对象从被创建、初始化、接收请求、处理请求,到最后被销毁的整个过程。这个过程由 Web 容器(如 Tomcat, Jetty) 全权管理。开发者不需要手动创建 new MyServlet(),容器会根据规则在合适的时机调用生命周期方法。

二、阶段一:初始化 (init)

目的:在 Servlet 开始处理客户端请求之前,进行一些一次性的、昂贵的资源加载工作(例如建立数据库连接、读取配置文件等)。

触发时机(两种)

  • 默认情况(延迟加载) :当容器启动后,Servlet 并不会立即被初始化。只有当 第一个请求 到达这个 Servlet 时,容器才会创建其实例并初始化。

  • 启动时加载(积极加载) :在 web.xml 中配置 <load-on-startup> 参数,可以让容器在 Web 应用启动时就创建和初始化 Servlet。数值越小,启动优先级越高。参数冲突时,Tomcat会自动处理。

XML 复制代码
<servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>com.example.MyServlet</servlet-class>
    <load-on-startup>1</load-on-startup> <!-- 数字1表示高优先级 -->
</servlet>

执行方法init(ServletConfig config)

  • 容器会调用这个方法。它只会被调用一次,在 Servlet 的整个生命周期中绝不会被调用第二次。

  • ServletConfig 对象包含了 Servlet 的初始化参数(在 web.xml 中配置)和 Servlet 上下文(ServletContext)的引用。

  • 通常,我们不会直接重写此方法,而是重写没有参数的 init() 方法。因为 GenericServlet 类已经提供了一个无参 init() 方法,它会在参数版的 init(ServletConfig) 方法中被调用。

代码示例

java 复制代码
public class MyServlet extends HttpServlet {

    private Connection dbConnection;

    @Override
    public void init() throws ServletException {
        // 这个方法在 init(ServletConfig) 中被调用,只执行一次
        try {
            // 执行一次性的初始化,比如建立数据库连接
            Class.forName("com.mysql.cj.jdbc.Driver");
            dbConnection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
            System.out.println("数据库连接在init()中建立");
        } catch (Exception e) {
            throw new ServletException("初始化数据库连接失败", e);
        }
    }
}

特点

  • init 方法执行完毕后,Servlet 就处于 "已就绪" 状态,随时可以处理客户端的请求。

三、阶段二:处理请求 (service)

目的:处理所有到达该 Servlet 的客户端请求并返回响应。

触发时机 :每一次客户端请求到达该 Servlet 时,容器都会调用 service 方法。

执行方法service(ServletRequest request, ServletResponse response)

  • 对于 HttpServlet,我们通常不需要重写这个方法。

  • HttpServlet 类已经为我们实现了标准的 service 方法。它会根据请求的 HTTP 方法(GET, POST, PUT, DELETE 等),自动调用相应的 doGet(), doPost(), doPut(), doDelete() 等方法。

  • 我们的主要工作就是重写那些 doXxx 方法来实现业务逻辑。

代码示例

java 复制代码
public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 处理GET请求(如点击链接,直接访问URL)
        response.getWriter().println("处理了一个GET请求");
        // 可以使用在init中初始化的dbConnection
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 处理POST请求(如表单提交)
        String user = request.getParameter("user");
        response.getWriter().println("你好, " + user + "! 这是一个POST请求。");
    }
}

特点

  • service 方法(及其分支 doGet/doPost)在 Servlet 的生命周期中可以被调用无数次

  • 容器会为每个请求创建一个新的请求对象(HttpServletRequest)响应对象(HttpServletResponse) ,然后开启一个新的线程来执行 service 方法。因此,Servlet 实例是单例多线程的

四、阶段三:销毁 (destroy)

目的:在 Servlet 生命周期结束时,释放它所占用的资源(例如关闭数据库连接、清理内存等)。

触发时机

  • Web 应用被卸载(或重新加载)。

  • Web 服务器被关闭。

  • 容器检测到需要重新加载 Servlet(某些容器的开发模式)。

执行方法destroy()

  • 这个方法也只会被调用一次,在 Servlet 生命周期结束时。

  • destroy() 方法调用之后,容器会释放这个 Servlet 实例,随后它会被垃圾回收器回收。

  • 容器会在调用 destroy() 之前,确保所有正在 service 方法中执行的线程都已结束或超时。

代码示例

java 复制代码
public class MyServlet extends HttpServlet {

    private Connection dbConnection;

    // ... init() 和 doGet/doPost 方法 ...

    @Override
    public void destroy() {
        // 释放资源
        try {
            if (dbConnection != null && !dbConnection.isClosed()) {
                dbConnection.close();
                System.out.println("数据库连接在destroy()中关闭");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

五、要点

单例多线程

一个 Servlet 类在容器中通常只有一个实例 。对于并发请求,容器会使用多个线程,每个线程执行同一个 Servlet 实例的 service 方法。因此,要特别注意线程安全 问题。记住,不要使用实例变量来存储请求相关的数据 ,因为它们会被所有线程共享。但是可以使用局部变量,它们是线程安全的。

相关推荐
我叫小白菜1 天前
【Servlet】使用idea2023创建Servlet JavaWeb
servlet
惜.己3 天前
linux中jenkins正常启动外部无法访问
linux·servlet·jenkins
Dest1ny-安全6 天前
Java代码审计-Servlet基础(1)
java·python·servlet
我是大头鸟6 天前
XMLHttpRequest 异步请求servlet 上传文件并且带有参数
ajax·servlet
我是大头鸟6 天前
XMLHttpRequest 发送json 格式的数据,servlet 接收
servlet·json·xmlhttprequest
_extraordinary_7 天前
Java Servlet(三)--- 写一个简单的网站,表白墙程序,登录功能的实现
java·开发语言·servlet
0wioiw07 天前
Java基础(①Tomcat + Servlet + JSP)
java·servlet·tomcat
卷Java7 天前
用户权限控制功能实现说明
java·服务器·开发语言·数据库·servlet·微信小程序·uni-app