Servlet 生命周期

Servlet 生命周期(完整解析)

Servlet 是 Java Web 核心组件,其生命周期完全由 Servlet 容器(如 Tomcat) 管理,从创建到销毁分为 初始化、请求处理、销毁 三个核心阶段,还包含加载与实例化的前置环节,整体流程如下:

一、生命周期完整阶段(按执行顺序)
阶段 触发时机 核心方法 执行次数 核心说明
1. 加载与实例化 ① 容器启动时(<load-on-startup> 配置);② 首次请求该 Servlet 时 无(容器调用构造方法) 仅 1 次 容器通过反射创建 Servlet 实例(默认单例,多实例需配置 SingleThreadModel
2. 初始化 实例化后立即执行 init(ServletConfig) 仅 1 次 初始化资源(如数据库连接、配置加载),可通过 ServletConfig 获取初始化参数
3. 请求处理 客户端发送请求(GET/POST 等)时 service(ServletRequest, ServletResponse)(底层调用 doGet/doPost 多次(每次请求) 核心业务逻辑处理,容器为每个请求分配独立线程,需注意线程安全
4. 销毁 ① 容器关闭;② 应用卸载;③ 容器检测到 Servlet 长时间未使用(极少触发) destroy() 仅 1 次 释放资源(如关闭连接、清理缓存),销毁后实例被垃圾回收
二、核心方法详解
1. 构造方法(实例化阶段)
  • 由容器调用,默认无参构造,若自定义有参构造需保证无参构造存在(否则容器无法实例化);
  • 单例模式下仅执行一次,所有请求共享同一个 Servlet 实例(需注意成员变量线程安全)。
2. init (ServletConfig config) 方法
  • 初始化入口,容器自动传入 ServletConfig 对象(包含 Servlet 名称、初始化参数、ServletContext);

  • 可重写 init() 无参方法(底层仍调用 init(ServletConfig)),示例:

    复制代码
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config); // 必须调用,否则ServletConfig无法被获取
        // 初始化数据库连接
        String dbUrl = config.getInitParameter("dbUrl");
        System.out.println("Servlet初始化,数据库地址:" + dbUrl);
    }
3. service (ServletRequest req, ServletResponse resp) 方法
  • 容器接收到请求后,先调用 service 方法,根据请求方式(GET/POST/PUT 等)自动分发到对应 doXxx 方法;

  • 若未重写 doGet/doPost,默认抛出 HttpServletMethodNotSupportedException

  • 示例(HttpServlet 子类):

    复制代码
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.service(req, resp); // 父类实现请求分发逻辑
        System.out.println("处理请求:" + req.getMethod());
    }
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("处理GET请求");
    }
4. destroy () 方法
  • 容器销毁 Servlet 前调用,用于释放资源,示例:

    复制代码
    @Override
    public void destroy() {
        // 关闭数据库连接、清理线程池等
        System.out.println("Servlet销毁,释放资源");
    }
三、关键特性与注意事项
  1. 单例特性:默认情况下,一个 Servlet 类在容器中仅存在一个实例,所有请求共用该实例 → 避免在 Servlet 中定义可变成员变量(易引发线程安全问题),建议使用局部变量或 ThreadLocal。

  2. 加载时机控制

    • 默认:首次请求时加载实例化(懒加载);

    • 配置 <load-on-startup>1</load-on-startup>(web.xml)或 @WebServlet(loadOnStartup = 1):容器启动时立即加载,数字越小优先级越高(用于初始化核心服务)

      <servlet> <servlet-name>MyServlet</servlet-name> <servlet-class>com.example.MyServlet</servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>dbUrl</param-name> <param-value>jdbc:mysql://localhost:3306/test</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>MyServlet</servlet-name> <url-pattern>/myServlet</url-pattern> </servlet-mapping>
  3. ServletContext 作用域 :生命周期贯穿整个 Web 应用,可通过 getServletContext() 获取,用于共享应用级数据(如全局配置)。

四、生命周期流程图(简化)
复制代码
容器启动/首次请求 → 加载Servlet类 → 实例化(构造方法) → init()初始化 → 
↓(每次请求)
service() → doGet/doPost处理请求 → 
↓(容器关闭/应用卸载)
destroy()销毁 → 实例被GC回收
相关推荐
tsyjjOvO11 小时前
SpringMVC 从入门到精通
数据仓库·hive·hadoop
Francek Chen16 小时前
【大数据存储与管理】分布式数据库HBase:05 HBase运行机制
大数据·数据库·hadoop·分布式·hdfs·hbase
zzzzzwbetter17 小时前
Hadoop完全分布式部署-Master的NameNode以及Slaver2的DataNode未启动
大数据·hadoop·分布式
weixin_4493108419 小时前
ETL转换和数据写入小满OKKICRM的技术细节
数据仓库·php·etl
IvanCodes20 小时前
Hive IDE连接及UDF实战
ide·hive·hadoop
yumgpkpm20 小时前
华为昇腾910B 开源软件GPUStack的介绍(Cloudera CDH、CDP)
人工智能·hadoop·elasticsearch·flink·kafka·企业微信·big data
lifewange2 天前
Hive数据库
数据库·hive·hadoop
五月天的尾巴3 天前
hive数据库模糊查询表名
hive·查询表名
蓝魔Y3 天前
hive—1.1、执行优化
hive
快乐非自愿3 天前
OpenClaw 生态适配:Hadoop/Hive 技能现状与企业级集成方案
大数据·hive·hadoop·分布式·openclaw