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

DispatcherServlet 初始化过程:SpringMVC 的 “启动引擎” 详解

DispatcherServlet 初始化过程:SpringMVC 的 “启动引擎” 详解

DispatcherServlet 是 SpringMVC 的 “前端控制器”,所有 HTTP 请求都先经过它处理,再分发到对应的控制器方法。它的初始化过程决定了 SpringMVC 能否正常工作 —— 从加载配置到初始化核心组件(如 HandlerMapping、ViewResolver),每一步都为后续请求处理打下基础。

本文将拆解 DispatcherServlet 的初始化流程,结合源码逻辑和通俗解释,帮你搞懂它是如何 “启动” 并做好准备的。

一、DispatcherServlet 的类层次:站在巨人的肩膀上

DispatcherServlet 并非孤立存在,它继承了多个抽象类,初始化逻辑分散在父类和自身中。核心继承关系如下:

HttpServlet(Servlet 规范)↓
HttpServletBean(Spring 扩展)↓
FrameworkServlet(SpringMVC 核心)↓
DispatcherServlet(具体实现)
  • HttpServlet:Servlet 规范的基础类,定义了 init()、service() 等生命周期方法;

  • HttpServletBean:将 Servlet 初始化参数(web.xml 或注解配置)绑定到自身属性(如配置文件路径);

  • FrameworkServlet:创建并初始化 SpringMVC 的容器(WebApplicationContext);

  • DispatcherServlet:初始化 SpringMVC 的核心组件(如 HandlerMapping、HandlerAdapter)。

初始化过程就是沿着这个继承链,从父类到子类逐步执行的。

二、初始化核心流程:3 大阶段详解

DispatcherServlet 的初始化始于 Servlet 容器(如 Tomcat)调用 init(ServletConfig) 方法,整个过程可分为 3 个核心阶段:

阶段 1:HttpServletBean 阶段 —— 解析初始化参数

HttpServletBean 是最顶层的 Spring 扩展类,它的核心作用是将 Servlet 配置参数(如 contextConfigLocation)绑定到自身属性,为后续容器初始化做准备。

关键代码与逻辑:
// HttpServletBean 重写 init 方法
@Override
public final void init() throws ServletException {// 1. 解析 web.xml 或注解中的初始化参数(如 <init-param>)PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);// 2. 将参数绑定到当前对象的属性(如 contextConfigLocation)BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);bw.setPropertyValues(pvs, true);// 3. 模板方法:留给子类(FrameworkServlet)实现具体初始化逻辑initServletBean();
}
核心作用:
  • 读取配置参数:如 contextConfigLocation(SpringMVC 配置文件路径,如 classpath:springmvc.xml);

  • 参数校验与绑定:确保必要参数存在(如配置文件路径),并设置到当前对象的属性中;

  • 触发下一阶段:通过 initServletBean() 模板方法,将初始化交给子类 FrameworkServlet。

阶段 2:FrameworkServlet 阶段 —— 创建 WebApplicationContext 容器

FrameworkServlet 是连接 Servlet 和 Spring 容器的关键,它的核心任务是创建并初始化 SpringMVC 的容器(WebApplicationContext),并将其与 Servlet 关联。

WebApplicationContext 是 SpringMVC 专属的容器,通常是 Spring 根容器(Root WebApplicationContext,由 ContextLoaderListener 初始化)的 “子容器”,专门管理控制器(@Controller)、拦截器等 Web 相关的 Bean。

关键代码与逻辑:
// FrameworkServlet 重写 initServletBean 方法
@Override
protected final void initServletBean() throws ServletException {// 1. 初始化 WebApplicationContext(SpringMVC 容器)this.webApplicationContext = initWebApplicationContext();// 2. 模板方法:留给子类(DispatcherServlet)实现后续初始化initFrameworkServlet();
}// 初始化 WebApplicationContext 的核心方法
protected WebApplicationContext initWebApplicationContext() {// 1. 获取父容器(Spring 根容器,通常由 ContextLoaderListener 创建)WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());// 2. 创建当前 Servlet 的 WebApplicationContext(子容器)WebApplicationContext wac = findWebApplicationContext();if (wac == null) {// 若未找到,以根容器为父,创建新的 WebApplicationContextwac = createWebApplicationContext(rootContext);}// 3. 容器初始化完成后,触发 onRefresh 方法(DispatcherServlet 会实现此方法)onRefresh(wac);// 4. 将容器存入 ServletContext,供后续使用ServletContext sc = getServletContext();sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);return wac;
}
核心作用:
  • 建立容器层次:以 Spring 根容器为父,创建 SpringMVC 子容器(避免 Web 组件污染全局容器);

  • 加载配置文件:根据 contextConfigLocation 加载 SpringMVC 的配置(如扫描 @Controller、定义视图解析器);

  • 触发组件初始化:通过 onRefresh(wac) 模板方法,让 DispatcherServlet 初始化核心组件。

阶段 3:DispatcherServlet 阶段 —— 初始化核心组件

DispatcherServlet 是最终的实现类,它在 onRefresh(wac) 方法中完成SpringMVC 核心组件的初始化,这些组件是处理请求的 “关键零件”(如 HandlerMapping、HandlerAdapter)。

关键代码与逻辑:
// DispatcherServlet 重写 onRefresh 方法
@Override
protected void onRefresh(ApplicationContext context) {// 初始化所有核心组件initStrategies(context);
}// 初始化策略(核心组件)
protected void initStrategies(ApplicationContext context) {// 1. 初始化文件上传解析器(处理 multipart/form-data 请求)initMultipartResolver(context);// 2. 初始化本地化解析器(处理国际化)initLocaleResolver(context);// 3. 初始化主题解析器(处理页面主题)initThemeResolver(context);// 4. 初始化 HandlerMapping(映射 URL 到控制器方法)initHandlerMappings(context);// 5. 初始化 HandlerAdapter(执行控制器方法,参数绑定)initHandlerAdapters(context);// 6. 初始化异常处理器(处理控制器方法抛出的异常)initHandlerExceptionResolvers(context);// 7. 初始化请求到视图名的转换器(如控制器返回字符串时转换为视图名)initRequestToViewNameTranslator(context);// 8. 初始化视图解析器(解析视图名到具体视图,如 JSP/Thymeleaf)initViewResolvers(context);// 9. 初始化 FlashMap 管理器(处理重定向时的参数传递)initFlashMapManager(context);
}
核心组件初始化细节:

每个组件的初始化逻辑相似:先从 Spring 容器中查找用户配置的 Bean,若未找到则使用默认实现。以最核心的 HandlerMapping 和 HandlerAdapter 为例:

  • HandlerMapping

    • 作用:根据 URL 和请求方法,找到对应的控制器方法(如 @GetMapping (“/user/{id}”) 绑定的方法);
    • 默认实现:若未配置,会使用 RequestMappingHandlerMapping(支持 @RequestMapping 注解)。
  • HandlerAdapter

    • 作用:执行找到的控制器方法,处理参数绑定、类型转换等;
    • 默认实现:若未配置,会使用 RequestMappingHandlerAdapter(支持 @RequestParam、@PathVariable 等注解)。

三、初始化完成的标志:可以处理请求了

当 initStrategies() 执行完毕,DispatcherServlet 的初始化就完成了。此时:

  • SpringMVC 容器(WebApplicationContext)已创建,包含所有控制器、拦截器等 Bean;

  • 核心组件(HandlerMapping、HandlerAdapter 等)已就绪,能处理请求映射、参数绑定、视图渲染等流程;

  • DispatcherServlet 进入 “就绪” 状态,等待接收 Servlet 容器转发的 HTTP 请求(通过 service() 方法处理)。

四、关键问题:初始化失败会怎样?

如果初始化过程中出现错误(如配置文件不存在、组件初始化失败),DispatcherServlet 会抛出 ServletException,导致 Servlet 初始化失败。此时:

  • 该 DispatcherServlet 无法处理任何请求;

  • Servlet 容器(如 Tomcat)会在日志中输出错误堆栈,提示具体失败原因(如 “找不到 springmvc.xml”)。

五、总结:DispatcherServlet 初始化的核心价值

DispatcherServlet 的初始化过程本质是 “准备工作”

  1. 读取配置(HttpServletBean 阶段);

  2. 创建容器(FrameworkServlet 阶段);

  3. 初始化组件(DispatcherServlet 阶段)。

这个过程确保了 SpringMVC 从 “启动” 到 “就绪” 的平滑过渡,为后续处理请求提供了必要的 “基础设施”。理解这个过程,能帮你在遇到初始化失败(如组件缺失、配置错误)时,快速定位问题根源(例如:若 HandlerMapping 未初始化,可能是未开启注解驱动 mvc:annotation-driven/)。

无论是传统 XML 配置还是 Spring Boot 自动配置,DispatcherServlet 的核心初始化逻辑始终不变 —— 这也是 SpringMVC 设计的精妙之处:通过分层抽象,让复杂的初始化过程变得有序且可扩展。


文章转载自:

http://6ESlN252.ydfLc.cn
http://BM5l3dmu.ydfLc.cn
http://d4XNf2Oz.ydfLc.cn
http://4gZZPzwd.ydfLc.cn
http://JMJYUmXJ.ydfLc.cn
http://3SbAmazn.ydfLc.cn
http://BwLCrEES.ydfLc.cn
http://C773GVZt.ydfLc.cn
http://ccf2GdLy.ydfLc.cn
http://Fl4Dauqq.ydfLc.cn
http://I3rHu5Di.ydfLc.cn
http://cYUPfDIs.ydfLc.cn
http://tIOE85HK.ydfLc.cn
http://q7tZTLNE.ydfLc.cn
http://IFOWyqsg.ydfLc.cn
http://mK80PlQh.ydfLc.cn
http://leJ9fzg9.ydfLc.cn
http://VTTPZ3hg.ydfLc.cn
http://aghRqnhw.ydfLc.cn
http://0ZnP2dvs.ydfLc.cn
http://PDt8gBOs.ydfLc.cn
http://njy7FrM6.ydfLc.cn
http://WGwaXEVy.ydfLc.cn
http://kcLzDpai.ydfLc.cn
http://IzDLsnVi.ydfLc.cn
http://Y2c9gitq.ydfLc.cn
http://pYOCRPs6.ydfLc.cn
http://rxTysQij.ydfLc.cn
http://2ye0kCII.ydfLc.cn
http://3i3DUTQY.ydfLc.cn
http://www.dtcms.com/a/371824.html

相关文章:

  • Simulink中使用Test sequence单元测试
  • 20250907-02:LangChain 架构和LangChain 生态系统包是什么
  • 大数据(非结构化数据,Spark,MongoDB)
  • FastAPI + LangChain 和 Spring AI + LangChain4j
  • Python基础语法篇:整数和浮点数,加减乘除怎么算?
  • 现成的AI模型:训练+评估框架汇总
  • 服务器断电引起的一例ORA-01207故障处理----惜分飞
  • 《MySQL基础——用户管理》
  • 【Linux】系统部分——进程间通信2(共享内存)
  • 【温室气体数据集】全球协作碳柱观测网络 COCCON
  • STM32 JLINK下载失败解决方案
  • JavaScript 中十种数组拷贝方法(从浅拷贝到深拷贝)
  • 04.事件中心模块
  • 【直接套模板】如何用 Web of Science 精准检索文献?
  • MCP与A2A
  • 数据库索引设计:在 MongoDB 中创建高效索引的策略
  • Shell 秘典(卷十)—— 服务器资源自动化监控脚本的设计与实现
  • 能源电力方向 的创业idea1
  • tf_keras包
  • PyTorch Lightning(训练评估框架)
  • Python进程,线程
  • java设计模式二、工厂
  • Claude Code核心功能操作指南
  • Python Mysql
  • Ansible 角色使用指南
  • 【c++】从三个类的设计看软件架构的哲学思考
  • 695章:使用Scrapy框架构建分布式爬虫
  • X448 算法签名验签流程深度解析及代码示例
  • 基于Apache Flink Stateful Functions的事件驱动微服务架构设计与实践指南
  • 算法题(201):传球游戏