详细介绍:Spring MVC 请求执行流程详解
1. 核心组件简介
在深入了解流程之前,第一需要认识流程中涉及的核心组件:
DispatcherServlet: 前端控制器(Front Controller),是整个流程的核心和入口。它接收所有请求,并负责协调各个组件共同完成请求处理,但其自身不处理业务逻辑。HandlerMapping: 处理器映射器,根据请求的 URL、手段等信息,找到能够处理该请求的处理器(Handler) 和拦截器(Interceptors)。HandlerAdapter: 处理器适配器,负责以统一的接口方式去实际执行找到的处理器(如@Controller中的方法)。因为处理器有多种形式(如基于注解的控制器、实现Controller接口的控制器等),适配器模式使得DispatcherServlet无需关心处理器的具体实现。HandlerInterceptor: 处理器拦截器,给出了在处理器执行前、后以及请求搞定后的拦截钩子,用于实现横切关注点(如日志、权限验证等)。Handler: 处理器,通常是我们编写的带有@Controller或@RestController注解的类中的方法,是实际执行业务逻辑的地方。ViewResolver: 视图解析器,根据控制器返回的逻辑视图名(如"home"),解析出具体的View对象(如 JSP, Thymeleaf 模板等)。View: 视图,负责将模型数据渲染成最终的响应内容(如 HTML 页面)。HandlerExceptionResolver: 异常解析器,负责处理请求处理过程中抛出的异常,将其转换为统一的错误响应(如错误页面、JSON 错误信息)。MultipartResolver: ** multipart 解析器**,用于解析文件上传等 multipart 类型的请求。
2. 请求执行流程详述
一个典型的 HTTP 请求在 Spring MVC 中的处理遵循一条清晰的“请求-响应”管道。其完整流程如下图所示:
阶段一:请求接收与分发
- 用户发起请求: 用户通过浏览器访问一个 URL(例如
http://example.com/app/products)。 - 请求到达
DispatcherServlet:- HTTP 请求首先被 Web 容器(如 Tomcat)捕获。
- 根据
web.xml或ServletRegistrationBean中的配置,匹配到请求路径的DispatcherServlet开始处理该请求。 DispatcherServlet是唯一的入口,它代表“前端控制器”设计模式。
阶段二:寻找处理器
- 查询处理器映射(
HandlerMapping):DispatcherServlet会查询所有配置的HandlerMappingbean(如RequestMappingHandlerMapping),询问哪一个Handler(控制器方法)能处理当前请求。HandlerMapping根据请求的 URL、HTTP 方法(GET、POST等)、请求头等信息进行匹配。- 如果找到匹配的处理器,
HandlerMapping会返回一个HandlerExecutionChain对象。该对象不仅包含了目标处理器(Handler),还包含了适用于该请求的所有HandlerInterceptor(拦截器)。
阶段三:执行预处理拦截器
- 执行拦截器的
preHandle方法:DispatcherServlet按顺序执行HandlerExecutionChain中所有拦截器的preHandle()方法。- 拦截器通常用于执行权限检查、日志记录、本地化设置等预处理逻辑。
- 重要: 如果任何一个拦截器的
preHandle方法返回false,则流程中断,直接返回,不会执行后续的处理器和拦截器。
阶段四:执行处理器(业务逻辑)
- 获取并调用处理器适配器(
HandlerAdapter):DispatcherServlet遍历所有配置的HandlerAdapter,找到第一个支持该类型处理器的适配器(如RequestMappingHandlerAdapter用于支持@RequestMapping注解的方法)。
- 实际执行处理器:
- 适配器调用处理器的具体方法(即我们编写的
@Controller中的方法),并传入相应的参数(如@RequestParam,@PathVariable,@RequestBody等注解修饰的参数)。参数解析由一系列的HandlerMethodArgumentResolver完成。 - 处理器执行业务逻辑(如调用 Service 层),并返回一个结果。这个结果通常被包装成一个
ModelAndView对象(包含模型数据和视图名),或者只是一个视图名,或者是一个被@ResponseBody注解的对象。
- 适配器调用处理器的具体方法(即我们编写的
阶段五:执行后处理拦截器
- 执行拦截器的
postHandle方法:- 处理器执行完毕后,
DispatcherServlet按逆序执行所有拦截器的postHandle()方法。 - 此时可以对
ModelAndView进行进一步的修改(如添加公共模型数据),但在前后端分离架构中(返回 JSON),此方法可能用处不大。
- 处理器执行完毕后,
阶段六:处理结果与渲染视图
处理返回结果:
- 如果处理器方法返回的是
String(视图名)或ModelAndView,DispatcherServlet会将其转发给ViewResolver。 ViewResolver根据逻辑视图名解析出具体的View对象(例如,将"products"解析为/WEB-INF/views/products.jsp)。- 如果方法有
@ResponseBody注解或控制器有@RestController注解,则结果会通过HttpMessageConverter直接写入 HTTP 响应体(返回 JSON/XML 等),跳过后面的视图渲染步骤。
- 如果处理器方法返回的是
渲染视图(如果需要):
DispatcherServlet将模型数据传递给解析得到的View对象,并调用其render()方法。View负责将模型数据与模板结合,生成最终的响应内容(如 HTML)。
阶段七:请求结束回调
- 执行拦截器的
afterCompletion方法:- 无论请求处理成功与否,在返回响应给客户端之前,
DispatcherServlet会按逆序执行所有拦截器的afterCompletion()方法。 - 此手段非常适合进行资源清理、记录请求完毕日志等操作。注意:即使前面的
preHandle或处理器执行过程中抛出异常,此方法也会被调用(但仅限那些preHandle成功执行并返回true的拦截器)。
- 无论请求处理成功与否,在返回响应给客户端之前,
阶段八:返回响应
- 返回响应: 最终生成的响应(可能是 HTML 页面,也可能是 JSON 数据)通过
DispatcherServlet返回给 Web 容器,并由容器最终发送回客户端。
4. 异常处理机制
异常处理贯穿于上述流程的多个环节:
- 处理器执行期间: 如果在任何阶段(特别是处理器执行时)抛出异常,
DispatcherServlet会捕获它。 - 委托给
HandlerExceptionResolver:DispatcherServlet会遍历所有配置的HandlerExceptionResolver(如@ExceptionHandler,ExceptionHandlerExceptionResolver),让它们来处理异常。 - 解析异常: 异常解析器可能会将异常转换为一个错误响应(如设置特定的 HTTP 状态码,返回一个错误视图
ModelAndView("error"),或者直接写入一个 JSON 错误信息)。 - 跳过后续步骤: 一旦发生异常,正常的流程(如
postHandle)会被跳过,但afterCompletion仍然会执行。
5. 总结与要点
- 中心化控制:
DispatcherServlet是流程的绝对核心,是所有请求的交通枢纽。 - 职责分离: 每个组件职责单一(映射、适配、执行、解析),符合设计模式的开闭原则,使得框架高度可配置和可扩展。
- 扩展点: 开发者可以通过实现或扩展
HandlerInterceptor,HandlerAdapter,ViewResolver,HandlerExceptionResolver等接口来定制流程的特定环节。 - 两种主要结果处理方式:
- 传统 MVC: 处理器返回视图名 ->
ViewResolver解析 ->View渲染。 - RESTful API: 处理器返回数据 +
@ResponseBody->HttpMessageConverter转换 -> 直接写入响应。
- 传统 MVC: 处理器返回视图名 ->

浙公网安备 33010602011771号