当前位置: 首页 > news >正文

JavaWeb——Servlet生命周期

一、什么是 Servlet 生命周期?

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

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

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

触发时机(两种)

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

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

<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) 方法中被调用。

代码示例

public class MyServlet extends HttpServlet {private Connection dbConnection;@Overridepublic 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 方法来实现业务逻辑。

代码示例

public class MyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 处理GET请求(如点击链接,直接访问URL)response.getWriter().println("处理了一个GET请求");// 可以使用在init中初始化的dbConnection}@Overrideprotected 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 方法中执行的线程都已结束或超时。

代码示例

public class MyServlet extends HttpServlet {private Connection dbConnection;// ... init() 和 doGet/doPost 方法 ...@Overridepublic void destroy() {// 释放资源try {if (dbConnection != null && !dbConnection.isClosed()) {dbConnection.close();System.out.println("数据库连接在destroy()中关闭");}} catch (SQLException e) {e.printStackTrace();}}
}

五、要点

单例多线程

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

http://www.dtcms.com/a/466078.html

相关文章:

  • JavaWeb——(web.xml)中的(url-pattern)
  • 企业网站建设合作协议范文天津城市建设大学网站
  • 新专业加速落地!设备采购先行,工业视觉人才培养破局。
  • FastAPI 入门:从环境搭建到实战开发的完整指南
  • Redis的String详解
  • MySQL事务隔离级别详解从读未提交到可串行化
  • 网站域名注册空间app外包
  • 赣州网站推广公司微网站建设是什么
  • 图扑 HT 架构下 AR 应用开发与行业解决方案实现
  • 测试实战心得
  • 网页网站设计价格为什么我做的视频网站播放不了
  • 前端框架深度解析:Vue.js 3 从 Composition API 到生态升级,解锁企业级开发新能力
  • DataX适合全量同步和简单的增量场景
  • 实体门店怎么使用小程序?实体店如何做小程序店铺?
  • 服装公司网站建设方案渭南做网站博创互联
  • 基于GPS/PTP/gPTP的自动驾驶数据同步授时方案
  • 福田网站建设龙岗网站建设龙岗网站建设龙岗网站建设中关村手机之家官网
  • solr负查询失效
  • GSPO如何消除高方差且不依赖routing replay
  • 南宁电子推广网站河南网站建设技术公司
  • 泰安房产网站建设设计网页公司哪家好
  • R语言基础保姆教程01--从工具到数据类型
  • MySQL索引失效揭秘:隐式类型转换的规则与案例!
  • Mysql杂志(三十)——索引失效情况
  • 百度企业网站建设wordpress 数据库设计
  • 10.程序地址空间_1
  • 6.0 Labview中的类面向对象编程-类的使用(OOP)
  • 上海精品网站建设想设计一个公司的网站
  • 【计算机】常见的缓存和查看方法
  • Linux 进程间通信机制详解