目录

1、Servlet 的生命周期

2、Spring 中一个 Controller 是一个Servlet 吗?

3、在 Spring 中有多少个 Servlet ?

4、DispatcherServlet 的生命周期

5、Servlet 生命周期和 ServletRequest 生命周期的区别


1、Servlet 的生命周期

Servlet 生命周期指的是 Servlet 对象从创建到销毁的整个过程,包括以下阶段:

  1. 加载和实例化阶段(loading and instantiation):当 Servlet 容器启动或者第一次请求某个 Servlet 时,会加载并创建 Servlet 对象的实例。在此阶段,容器会调用 ServletContext 的 getServlet 方法来获取 Servlet 实例,并调用其 init 方法进行初始化。在 init 方法中,Servlet 可以进行一些初始化工作,如加载配置文件、建立数据库连接等。

  2. 就绪阶段(ready):当 Servlet 初始化完成后,容器会将其放入就绪状态,表示它已经准备好处理客户端请求了。

  3. 请求处理阶段(request handling):当客户端发起请求时,Servlet 容器会为每个请求创建一个新的线程,并调用 Servlet 的 service 方法处理请求。在 service 方法中,Servlet 可以读取请求数据、进行业务处理,并生成响应数据发送给客户端。

  4. 销毁阶段(destruction):当 Servlet 容器关闭或者 Web 应用程序被卸载时,会调用 Servlet 的 destroy 方法,此时 Servlet 会执行一些清理工作,如关闭数据库连接、保存会话数据等。在销毁阶段结束后,Servlet 实例将被销毁并释放资源。

需要注意的是,Servlet 生命周期中 init 和 destroy 方法只会在 Servlet 实例创建和销毁时被调用一次,而 service 方法则会在每个请求到达时被调用一次。此外,Servlet 还可以实现其他生命周期方法,如 init(ServletConfig config)、getServletConfig() 等,以提供更加灵活的初始化和配置方式。

一般情况下,Servlet只有在容器关闭时才会被销毁,但也可以通过Servlet的destroy()方法手动销毁Servlet。当Servlet不再被需要时,可以通过调用destroy()方法来释放资源、关闭数据库连接、取消注册等操作。Servlet的生命周期是整个应用程序中Servlet的初始化、请求处理和销毁的过程。

Servlet 生命周期流程如下图所示:

下面通过一个案例加深对 Servlet 生命周期的理解:

@WebServlet("/myServletLife")
public class MyServletLife extends HttpServlet {private static final long serialVersionUID = 1L;private int initCount = 0;private int httpCount = 0;private int destoryCount = 0;@Overridepublic void destroy() {destoryCount++;super.destroy();// 向控制台输出destory方法被调用次数System.out.println("**********************************destroy方法:" + destoryCount + "*******************************");}@Overridepublic void init() throws ServletException {initCount++;super.init();// 向控制台输出init方法被调用次数System.out.println("调用init方法:" + initCount);}public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {httpCount++;// 控制台输出doGet方法次数System.out.println("doGet方法:" + httpCount);// 设置返回页面格式与字符集resp.setContentType("text/html;charset=UTF-8");PrintWriter writer = resp.getWriter();// 向页面输出writer.write("初始化次数:" + initCount + "<br/>" + "处理请求次数:" + httpCount + "<br/>" + "销毁次数:" + destoryCount);writer.close();}protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {this.doGet(request, response);}
}

启动 Tomcat,在地址栏输入“localhost:8080/web/myServletLife”,多次访问 MyServlet,结果如下图。

关闭 Tomcat 服务器,控制台输出如下图

2、Spring 中一个 Controller 是一个Servlet 吗?

在 Spring 中,每个 Controller 类并不是一个 Servlet,而是通过 Servlet 映射器(HandlerMapping)和适配器(HandlerAdapter)来将 HTTP 请求映射到相应的方法进行处理。

具体来说,Spring MVC 框架使用了 DispatcherServlet 作为前置控制器,负责接收客户端的请求并将请求分发给相应的 Controller 进行处理。DispatcherServlet 会根据配置的 Servlet 映射器和适配器来选择合适的 Controller 类,并将请求转发给该类中的具体方法进行处理。在方法中,可以通过注解来定义请求参数、返回值和异常处理等信息,从而更加方便地实现业务逻辑的编写。

因此,虽然每个 Controller 类并不是一个 Servlet,但在 Spring MVC 框架中,它们可以像 Servlet 一样接收并处理 HTTP 请求。同时,Spring 还提供了很多方便的注解和工具类来简化 Controller 类的编写,使得开发者可以更加专注于业务逻辑的实现。

// Controller 只是 springmvc 中的处理器,通过 Servlet 映射器去匹配

3、在 Spring 中有多少个 Servlet ?

在一个 Spring 应用程序中,通常会有一个或多个 Servlet。其中,最常见的是 DispatcherServlet,它是 Spring MVC 框架的核心组件之一,负责接收客户端请求并将请求分发给相应的 Controller 进行处理。

除了 DispatcherServlet,Spring 还提供了一些其他的 Servlet,包括:

  1. ContextLoaderServlet:用于在 Web 应用程序启动时加载 Spring 配置文件,并将 ApplicationContext 对象存储在 ServletContext 中供其他组件使用。

  2. FrameworkServlet:是 DispatcherServlet 的父类,用于处理与 Spring 框架相关的 Servlet 请求,如请求映射、视图解析等。

  3. HttpPutFormContentFilter:用于处理 PUT 请求中的表单数据。

  4. OpenEntityManagerInViewFilter:用于在 Web 请求结束时自动关闭 EntityManager,以避免因为长时间持有 EntityManager 导致的内存泄漏。

  5. DelegatingFilterProxy:是一个通用的过滤器代理,可以将过滤器的实现委托给 Spring 容器中的任意一个 Bean 实例。

需要注意的是,除了 DispatcherServlet 外,其他的 Servlet 大多是一些辅助性的组件,用于解决一些特定的问题,如处理 PUT 请求中的表单数据、自动关闭 EntityManager 等。开发者在使用 Spring 框架时,一般只需要关注 DispatcherServlet 的配置和使用即可。

4、DispatcherServlet 的生命周期

DispatcherServlet 是 Spring MVC 框架中的一个核心组件,它作为前置控制器负责接收客户端请求并将请求分发给相应的 Controller 进行处理。它的生命周期可以分为以下几个阶段:

  1. 初始化阶段(Initialization):在容器启动时,Servlet 容器会自动创建 DispatcherServlet 实例并调用其 init() 方法进行初始化。在初始化阶段中,DispatcherServlet 会读取并解析配置文件(如 web.xml 或注解配置等),创建必要的组件对象(如 HandlerMapping、HandlerAdapter 等),并将它们存储在 ServletContext 中,以便于在后续的请求处理中使用。

  2. 请求处理阶段(Request Handling):当客户端发送请求时,Servlet 容器会将请求交给 DispatcherServlet 进行处理。在请求处理阶段中,DispatcherServlet 会根据配置的 HandlerMapping 找到匹配的 Controller,然后调用相应的 Controller 方法进行处理。在方法执行过程中,DispatcherServlet 会根据配置的 HandlerAdapter 对请求参数进行解析,将其转换为方法所需的类型,并将方法的执行结果封装为 ModelAndView 对象。最后,DispatcherServlet 会调用 ViewResolver 将 ModelAndView 对象转换为相应的视图,并将视图渲染后的结果返回给客户端。

  3. 销毁阶段(Destruction):当 Servlet 容器关闭时,会调用 DispatcherServlet 的 destroy() 方法进行销毁。在销毁阶段中,DispatcherServlet 会释放所有的资源(如 HandlerMapping、HandlerAdapter 等),并清除 ServletContext 中的相应对象。

需要注意的是,由于 DispatcherServlet 是一个单例对象,因此它的生命周期与整个应用程序的生命周期是一致的,即在应用程序启动时创建,在应用程序关闭时销毁。在处理请求时,DispatcherServlet 会创建一个新的线程来处理每个请求,因此它的请求处理阶段是并发的,可以处理多个请求同时到达的情况。

 DispatcherServlet 异步处理请求的源码展示:

在 DispatcherServlet 中创建新的线程来处理请求的代码位于 doService() 方法中。以下是部分源码示例:

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {// 获取处理器HandlerExecutionChain mappedHandler = getHandler(request);// 获取处理器适配器HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// 使用 Callable 封装请求和响应final ModelAndView exMv = ha.handle(request, response, mappedHandler.getHandler());// 创建新线程处理请求if (asyncManager.isConcurrentHandlingStarted()) {return;}// 判断是否支持异步处理if (exMv != null && exMv.isAsyncStarted()) {if (isAsyncDispatch(request)) {// 使用 Spring 的异步机制进行处理if (request.getAsyncContext().getTimeout() > 0) {asyncManager.setTaskTimeout(request.getAsyncContext().getTimeout());}asyncManager.startCallableProcessing(new DispatcherServletCallable(exMv), request, response, mappedHandler.getHandler());return;}}// 同步处理请求ha.handle(request, response, mappedHandler.getHandler());
}

可以看到,在 doService() 方法中,当判断可以使用异步处理时,DispatcherServlet 会使用 Spring 的异步机制进行处理,其中 asyncManager.startCallableProcessing() 方法会创建一个新的线程来处理请求。这样就实现了异步处理请求,提高了系统的吞吐量和响应速度。

5、Servlet 生命周期和 ServletRequest 生命周期的区别

Servlet的生命周期是整个应用程序中Servlet的初始化、请求处理和销毁的过程,而ServletRequest的生命周期是单次请求中HttpServletRequest和HttpServletResponse对象的创建和销毁的过程。

具体来说,当Servlet容器接收到一个请求时,容器会为该请求创建一个新的HttpServletRequest对象和HttpServletResponse对象,这两个对象只在当前请求中有效,处理完请求后会被销毁,如果是同一个客户端发起的新请求,Servlet容器会再次创建HttpServletRequest和HttpServletResponse对象。// req和rep只在当前请求中有效,处理完请求后会被销毁,可以理解为方法的出栈

在ServletRequest的生命周期中,HttpServletRequest和HttpServletResponse对象会被传递给Servlet的service()方法,Servlet可以通过这两个对象获取请求参数、设置响应头、发送响应数据等操作。当请求处理完毕后,Servlet容器会自动销毁HttpServletRequest和HttpServletResponse对象,释放资源。

所以,Servlet的生命周期是应用程序级别的,而ServletRequest的生命周期是请求级别的。

Servlet 的生命周期详解相关推荐

  1. Fragment生命周期详解

    关于Fragment的生命周期,博主写过Activity与Fragment生命周期详解,基本上把Fragment的生命周期详细介绍过,但是那仅仅是创建一个Fragmnet时的生命周期,而事实上Frag ...

  2. Android面试之Activity生命周期详解

    Activity生命周期详解 一 Activity的四种状态: Activity的生命周期中存在四种基本的状态:活动状态(Active/Runing),暂停状态(Paused),停止状态(Stoppe ...

  3. Fragment的懒加载与生命周期详解

    提示:本文仅为笔者学习记录 Fragment的懒加载与生命周期详解 什么是懒加载 了解Fragment的生命周期 onAttach onCreate onCreateView onActivityCr ...

  4. vue 声明周期函数_Vue 生命周期详解

    Vue 生命周期详解 Vue 生命周期流程 最开始,用户使用 new Vue() 创建根 Vue 实例,或者 Vue 实例化子组件都会调用_init方法(我们将这两种实例都称为vm): functio ...

  5. 01.软件项目管理与敏捷方法——敏捷项目生命周期详解笔记

    01.软件项目管理与敏捷方法--敏捷项目生命周期详解笔记 00.与其说是船还不如说是熟练的航行技术保证了成功的航行.--George William Curtis 01.敏捷项目是一个按照敏捷宣言宗旨 ...

  6. taro生命周期详解

    taro生命周期详解 taro介绍 生命周期 react的钩子函数 为兼容小程序的钩子函数 个别生命周期详解以及注意 1.render()函数 2.constructor()构造函数 3.在各个生命周 ...

  7. Eclipse中Maven常用命令以及Maven生命周期详解

    Eclipse中maven常用的命令 在某一个maven项目右键快捷方式,然后点击Run As就可以发现几个Maven的命令: Maven Build: 这个命令用于编译Maven工程,执行命令后会在 ...

  8. Spring 生命周期详解

    Spring 生命周期详解 一.传统JAVA bean的生命周期 使用Java关键字 new 进行Bean 的实例化,然后该Bean 就能够使用了. 一旦bean不再被使用,则由Java自动进行垃圾回 ...

  9. flutter 生命周期详解

    flutter 生命周期详解 简介 一.widget 生命周期 二.APP 生命周期 总结 简介 众所周知,程序是有生命周期的,那么flutter 的生命周期是什么呢? flutter 的生命周期大体 ...

最新文章

  1. Internet Explorer 已停止工作 解决办法
  2. (二)GitHub的使用随记
  3. SVN创建不了资源库位置 解决方案
  4. 连载08:软件体系设计新方向:数学抽象、设计模式、系统架构与方案设计(简化版)(袁晓河著)...
  5. checkbox全选和反选功能
  6. css3之背景属性之background-size
  7. java 代码重排_Java中指令重排
  8. 【洛谷p1164】小A点菜
  9. 快速计算网络地址和广播地址
  10. mysql 根据经纬度查询范围点
  11. 实现微信公众号评论回复功能
  12. burpSuit抓取app的数据包
  13. HUAWEIWATCH GT3有哪些功能?华为新款手表测评
  14. Pytorch 利用Facenet和Retinaface实现人脸识别
  15. 网易云课堂---布尔教育《8小时学会html》 笔记
  16. Developing 2D Games with Unity 免积分下载
  17. 动画程序时长缩放是什么意思_Pr预设:2000种文字标题排版指示线图形动画无缝转场剪辑工具包...
  18. 《Unity Magica Cloth从入门到详解》之(8)视野外剔除系统
  19. 那些年,关于 Java 的那些事儿
  20. 颜色的搭配 色彩标准卡 各行各业设计人员必看

热门文章

  1. 互联网精准广告定向技术: 一切你该了解的知识总结与整理
  2. Watir 截图两种方式,保存截图到PPT里面
  3. 企业管理软件选型九大误区
  4. 骨传导耳机哪个品牌比较好?骨传导耳机推荐
  5. 数据处理技巧(4):txt/word等快速选中部分数据
  6. 【小沐学python】(一)Python开发准备
  7. HBase入门介绍(从基础到架构)
  8. 分布式面试必问题!为什么说CAP不能兼顾?
  9. RH236配置IP故障转移--配置NFS Ganesha
  10. 3、Web 窗体的基本控件——按钮控件(Button,LinkButton)