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

SpringMVC 执行流程详解

目录

  • 前言
  • 1. SpringMVC 的核心组件概述
    • 1.1 DispatcherServlet
    • 1.2 HandlerMapping
    • 1.3 HandlerAdapter
    • 1.4 拦截器(HandlerInterceptor)
    • 1.5 ViewResolver
  • 2. SpringMVC 的执行流程详解
    • 2.1 接收请求并分发
    • 2.2 获取 HandlerExecutionChain
    • 2.3 获取 HandlerAdapter
    • 2.4 执行拦截器的 preHandle 方法
    • 2.5 调用处理器方法(HandlerMethod)
    • 2.6 执行拦截器的 postHandle 方法
    • 2.7 异常处理(全局异常处理器)
    • 2.8 解析视图
    • 2.9 渲染视图并响应客户端
    • 2.10 执行拦截器的 afterCompletion 方法
  • 3. SpringMVC 执行流程的整体架构
  • 结语

前言

SpringMVC 是 Java Web 开发中广泛应用的 MVC 框架,它以其高效、灵活的设计受到了开发者的青睐。在 SpringMVC 中,从接收到请求到最终给浏览器返回响应,涉及多个核心组件和步骤,每个环节都体现了框架的设计思想和高内聚低耦合的原则。本文将详细解析 SpringMVC 的执行流程,帮助读者全面了解其工作原理,为实际开发和问题排查提供理论支持。

1. SpringMVC 的核心组件概述

在深入了解执行流程之前,有必要先简单介绍几个核心组件:
在这里插入图片描述

1.1 DispatcherServlet

DispatcherServlet 是 SpringMVC 的核心调度器,负责接收 HTTP 请求并调度到相应的处理器。它相当于整个框架的中枢神经,将请求处理的每个环节串联起来。所有的请求都会先到达 DispatcherServlet

1.2 HandlerMapping

HandlerMapping 的职责是将请求 URL 映射到对应的处理器(Handler)。在 SpringMVC 中,处理器通常是一个注解标注的控制器方法(如 @RequestMapping 标注的方法)。

1.3 HandlerAdapter

HandlerAdapter 是对处理器的包装和适配器模式的应用。它负责调用具体的处理器方法并将结果返回。

1.4 拦截器(HandlerInterceptor)

拦截器是 SpringMVC 提供的一种扩展机制,用于在请求处理的不同阶段执行额外的逻辑。它包括 preHandle(请求处理前)、postHandle(请求处理后但视图渲染前)和 afterCompletion(请求完成后)三个方法。

1.5 ViewResolver

ViewResolver 是视图解析器,负责将处理器方法返回的逻辑视图名解析为实际的视图对象(如 JSP、Thymeleaf 模板等),并最终渲染视图。

2. SpringMVC 的执行流程详解

接下来,我们从请求到响应的整个流程,逐步剖析 SpringMVC 的执行机制。
在这里插入图片描述

2.1 接收请求并分发

当客户端发出 HTTP 请求时,DispatcherServlet 是第一个接收到请求的组件。在初始化阶段,DispatcherServlet 已经加载了 HandlerMappingHandlerAdapter 等必要组件,并完成了相关配置。当请求到达时,它会先解析请求路径和方法类型(如 GET、POST),以便后续的处理。

@Override
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 核心调度逻辑
    HandlerExecutionChain mappedHandler = getHandler(request);
    if (mappedHandler == null) {
        noHandlerFound(request, response);
        return;
    }
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    ...
}

2.2 获取 HandlerExecutionChain

DispatcherServlet 通过调用 HandlerMapping 来找到对应的处理器,并生成一个 HandlerExecutionChain 对象。这个对象不仅包含了处理器本身,还包括相关的拦截器链。HandlerMapping 会根据配置的规则(如注解映射、URL 配置等)来寻找处理器。

常见的 HandlerMapping 实现

  • RequestMappingHandlerMapping:处理基于注解的映射规则。
  • SimpleUrlHandlerMapping:用于传统的配置方式。

2.3 获取 HandlerAdapter

找到处理器后,DispatcherServlet 会通过 HandlerAdapter 调用处理器的具体方法。HandlerAdapter 充当适配器的角色,使得不同类型的处理器(如注解控制器、接口实现)都能统一被调用。

HandlerAdapter 的作用

HandlerAdapter 将处理器的逻辑抽象化,使框架可以灵活扩展。开发者在实现自定义处理器时,可以通过实现对应的 HandlerAdapter 来适配新的处理逻辑。
在这里插入图片描述

2.4 执行拦截器的 preHandle 方法

在调用处理器方法之前,DispatcherServlet 会执行所有拦截器的 preHandle 方法。如果某个拦截器返回 false,请求会被中止,并不会执行后续的处理器方法。

拦截器的典型应用场景包括:

  • 用户身份认证
  • 权限检查
  • 请求参数预处理

2.5 调用处理器方法(HandlerMethod)

HandlerAdapter 调用处理器方法时,会自动注入参数(如请求参数、路径变量、表单数据等),并接收返回值。处理器方法的返回值可以是多种类型,例如:

  • 字符串(视图名称)
  • JSON 数据(配合 @ResponseBody@RestController 使用)
  • 自定义对象

此阶段的核心任务是处理业务逻辑,并将结果封装起来。

2.6 执行拦截器的 postHandle 方法

处理器方法执行完毕后,拦截器的 postHandle 方法会被调用。此时,控制器方法的结果已经生成,但视图还未渲染。postHandle 常用于修改模型数据或进行日志记录。

2.7 异常处理(全局异常处理器)

如果在请求处理过程中抛出异常,SpringMVC 会触发异常处理机制。全局异常处理器(如 @ControllerAdvice 中定义的 @ExceptionHandler)可以捕获并处理这些异常,从而返回友好的错误信息。

异常处理机制

  • 优先匹配 @ExceptionHandler 注解的方法。
  • 如果未找到,调用全局异常解析器(HandlerExceptionResolver)。

2.8 解析视图

处理器方法返回视图名称后,DispatcherServlet 会调用 ViewResolver 将逻辑视图名解析为具体的视图对象。视图解析器的典型实现包括:

  • InternalResourceViewResolver:解析 JSP 文件路径。
  • ThymeleafViewResolver:支持 Thymeleaf 模板引擎。

2.9 渲染视图并响应客户端

视图解析完成后,SpringMVC 会将模型数据填充到视图中,并将最终渲染的内容写入 HTTP 响应。对于 JSON 数据,通常通过 MappingJackson2HttpMessageConverter 等消息转换器直接写入。

2.10 执行拦截器的 afterCompletion 方法

最后,拦截器的 afterCompletion 方法会在视图渲染完成后执行。这一阶段适合用于资源清理或记录最终的处理状态。

3. SpringMVC 执行流程的整体架构

通过上面的分析,我们可以总结出 SpringMVC 的执行流程图:

  1. 客户端发出请求 -> DispatcherServlet 接收
  2. 寻找处理器(Handler) -> 执行拦截器
  3. 调用处理器方法 -> 返回结果
  4. 异常处理(若有) -> 解析视图 -> 渲染视图
  5. 执行拦截器的完成方法 -> 响应客户端

结语

SpringMVC 的执行流程清晰而高效,其设计充分体现了开闭原则和职责分离的思想。从接收请求到响应结果,多个组件紧密配合,同时提供了丰富的扩展点,允许开发者根据需求自定义功能。理解这些流程不仅有助于开发高质量的 Web 应用,还能更快速地定位和解决问题。


http://www.kler.cn/a/407749.html

相关文章:

  • Unity图形学之Surface Shader结构
  • 3D Gaussian Splatting在鱼眼相机中的应用与投影变换
  • 服务机器人三甲坎德拉:用智能化开启售后服务新篇章
  • 【Mysql】开窗聚合函数----SUM,AVG, MIN,MAX
  • C语言——break、continue、goto
  • 基于ToLua的C#和Lua内存共享方案保姆级教程
  • 架构图解析:如何构建高效的微服务系统
  • Cocos creator 3.8 支持的动画 7
  • 2024年09月CCF-GESP编程能力等级认证Scratch图形化编程二级真题解析
  • 【Apache paimon】-- 7 -- tag 创建与管理
  • 【C++】list使用详解
  • 【从零开始的LeetCode-算法】3297. 统计重新排列后包含另一个字符串的子字符串数目 I
  • java操作doc——java利用Aspose.Words操作Word文档并动态设置单元格合并
  • 基于Java Springboot高校教室资源管理系统
  • React面试宝典
  • 丹摩|重返丹摩(下)
  • 低代码搭建crm系统实现财务管理功能模块
  • ORACLE删不掉job,如何解决。
  • Ansys Zemax | 使用多重结构操作数控制单一结构系统中的参数
  • Linux|内存级文件原理
  • Angular Essentials 扩展包教程
  • R中单细胞RNA-seq数据分析教程 (2)
  • 大数据技术之SparkCore
  • 视频截断,使用 FFmpeg
  • torch_geometric使用手册-Creating Message Passing Networks(专题二)
  • Docker 配置 HTTP 和 HTTPS 网络代理