SpringMVC核心流程
SpringMVC 是 Spring 用于 web 开发的模块,基于 Servlet 封装,核心是「前端控制器(DispatcherServlet)」,统一调度所有组件,实现请求的接收、处理、响应全流程。
一、SpringMVC 完整请求处理流程 🔴
核心逻辑:浏览器发起请求 → 前端控制器统一接收 → 组件协同处理 → 后端方法执行 → 响应返回浏览器,共10步。
1. 完整流程 🔴
-
浏览器发起 HTTP 请求(如 GET /user/1、POST /user),请求被 web 服务器(如 Tomcat)接收,转发给 SpringMVC 的 DispatcherServlet(前端控制器,所有请求的入口);
-
DispatcherServlet 接收请求后,调用HandlerMapping(处理器映射器),根据请求 URL 和配置(如 @RequestMapping),找到对应的 Handler(后端控制器,即 Controller 中的方法);
-
HandlerMapping 返回 Handler 的执行链(包含 Handler 和对应的 HandlerInterceptor 拦截器)给 DispatcherServlet;
-
DispatcherServlet 调用 HandlerAdapter(处理器适配器),适配当前 Handler(处理参数绑定、JSON 解析等),准备执行 Handler;
-
执行 HandlerInterceptor 拦截器的
preHandle方法(前置拦截,如权限校验,返回 true 则继续,false 则终止); -
HandlerAdapter 调用 Handler(后端 Controller 中的目标方法),执行业务逻辑,返回 ModelAndView(包含模型数据和视图名称);
-
执行 HandlerInterceptor 拦截器的
postHandle方法(后置拦截,可修改 ModelAndView,如添加全局数据); -
DispatcherServlet 调用 ViewResolver(视图解析器),根据 ModelAndView 中的视图名称,解析出具体的视图(如 JSP、HTML,或 JSON 数据);
-
执行 HandlerInterceptor 拦截器的
afterCompletion方法(完成拦截,如清理资源,无论成功/失败都会执行); -
视图渲染(将模型数据填充到视图中),生成响应结果(HTML/JSON),通过 DispatcherServlet 返回给浏览器,请求处理完成。
2. 简化流程
浏览器 → Tomcat → DispatcherServlet(前端控制器)→ HandlerMapping(找 Handler)→ HandlerAdapter(适配执行)→ Handler(Controller 方法)→ ModelAndView → ViewResolver(解析视图)→ 拦截器(pre/post/after)→ 浏览器
二、核心组件职责 🔴
SpringMVC 的核心组件共5个,各司其职,由 DispatcherServlet 统一调度。
1. DispatcherServlet(前端控制器,核心中的核心)
-
核心职责:统一接收所有 HTTP 请求,调度其他所有组件,是 SpringMVC 的“入口”和“中枢”;
-
关键作用:
-
接收浏览器请求,转发给 HandlerMapping;
-
协调 HandlerAdapter、ViewResolver 等组件工作;
-
统一处理响应,返回结果给浏览器;
-
简化组件之间的耦合,所有组件都通过它交互。
-
-
总结:“DispatcherServlet 是 SpringMVC 的核心,负责接收请求、调度组件、返回响应,相当于整个请求链路的‘总指挥’”。
2. HandlerMapping(处理器映射器)
-
核心职责:根据请求 URL 和配置,找到对应的 Handler(Controller 中的目标方法);
-
关键作用:
-
解析请求 URL,匹配对应的 @RequestMapping 注解(或 XML 配置);
-
返回 Handler 的执行链(包含 Handler 和拦截器);
-
常用实现:RequestMappingHandlerMapping(默认,适配注解式 Controller)。
-
-
总结:“HandlerMapping 负责‘找方法’,根据请求 URL 找到对应的 Controller 方法”。
3. HandlerAdapter(处理器适配器)
-
核心职责:适配 Handler,负责参数绑定、JSON 解析,调用 Handler 执行;
-
关键作用:
-
处理请求参数绑定(如 @RequestParam、@PathVariable 注解的参数解析);
-
处理请求体解析(如 @RequestBody 接收 JSON,依赖 HttpMessageConverter);
-
调用 Handler(Controller 方法),执行具体业务逻辑;
-
常用实现:RequestMappingHandlerAdapter(默认,适配注解式 Handler)。
-
-
总结:“HandlerAdapter 负责‘适配方法’,解析请求参数,调用 Controller 方法执行”。
4. HandlerInterceptor(拦截器)
-
核心职责:对请求进行拦截,实现权限校验、日志记录、数据预处理等增强功能;
-
关键作用(3个核心方法,按执行顺序):
-
preHandle:请求处理前执行(前置拦截),返回 true 继续执行,返回 false 终止请求(如权限校验失败,直接返回);
-
postHandle:请求处理后、视图渲染前执行(后置拦截),可修改 ModelAndView(如添加全局用户信息);
-
afterCompletion:视图渲染后、请求完成后执行(完成拦截),用于清理资源(如关闭流),无论请求成功/失败都会执行。
-
-
总结:“拦截器负责‘拦截请求’,在请求处理的不同阶段做增强,如权限校验、日志记录”。
5. ViewResolver(视图解析器)
-
核心职责:根据 ModelAndView 中的视图名称,解析出具体的视图对象;
-
关键作用:
-
接收 ModelAndView(模型数据+视图名称),解析视图名称(如“index”→“/WEB-INF/views/index.jsp”);
-
生成 View 视图对象,用于渲染模型数据,生成响应结果(HTML);
-
若返回 JSON 数据(无视图),则无需 ViewResolver 参与(由 HttpMessageConverter 处理)。
-
-
总结:“ViewResolver 负责‘解析视图’,将视图名称转换成具体的视图,用于渲染数据”。
6. HttpMessageConverter(消息转换器,补充重点)
-
核心职责:处理请求体和响应体的序列化/反序列化,重点是 JSON 数据的解析与返回;
-
关键作用:
-
请求阶段:将浏览器发送的 JSON 数据(请求体)反序列化为 Java 对象(适配 @RequestBody 注解);
-
响应阶段:将 Java 对象序列化为 JSON 数据(适配 @ResponseBody 注解),返回给浏览器;
-
常用实现:MappingJackson2HttpMessageConverter(默认,依赖 Jackson 依赖,处理 JSON)。
-
-
总结:“HttpMessageConverter 负责‘JSON 序列化/反序列化’,实现前后端 JSON 数据交互”。
三、拦截器 vs 过滤器 🔴
核心区别:过滤器是 Servlet 规范,拦截器是 SpringMVC 组件,两者执行顺序、作用范围、功能都不同,重点“执行顺序”和“核心区别”。
1. 核心区别对比 🔴
| 对比维度 | HandlerInterceptor(拦截器) | Filter(过滤器) |
|---|---|---|
| 所属规范 | SpringMVC 自定义组件,依赖 Spring 框架 | Servlet 规范,属于 Java Web 标准,不依赖 Spring |
| 拦截范围 | 仅拦截 SpringMVC 管理的请求(即 Controller 方法的请求) | 拦截所有 web 请求(包括静态资源、JSP、Servlet,不区分是否由 Spring 管理) |
| 执行顺序 | 在 Filter 之后执行(Filter → DispatcherServlet → 拦截器) | 在 DispatcherServlet 之前执行(最先拦截请求) |
| 执行时机 | 在请求处理的不同阶段(pre/post/after)执行,可精准控制 | 仅在请求进入容器后、响应返回前执行,时机单一 |
| 依赖对象 | 可注入 Spring 容器中的 Bean(如 Service),能调用业务逻辑 | 无法注入 Spring Bean,依赖 Servlet 容器,功能有限 |
| 适用场景 | 权限校验、日志记录、业务数据预处理(与业务相关) | 编码过滤(如 UTF-8 编码)、敏感词过滤、静态资源拦截(与业务无关) |
2. 执行顺序 🔴
浏览器发起请求 → Filter(过滤器)→ DispatcherServlet(前端控制器)→ HandlerInterceptor(preHandle)→ Handler(Controller 方法)→ HandlerInterceptor(postHandle)→ ViewResolver(视图解析)→ HandlerInterceptor(afterCompletion)→ Filter → 浏览器响应
四、常用注解
重点注解的“作用”和“使用场景”,避免混淆,尤其是 @RequestBody 和 @RequestParam 的区别。
| 注解 | 核心作用 | 使用场景 | 注意事项 |
|---|---|---|---|
| @RequestMapping | 映射请求 URL 到 Controller 方法,可指定请求方式(GET/POST) | 类级别(指定统一前缀)、方法级别(指定具体路径) | 可简写为 @GetMapping、@PostMapping(更简洁) |
| @RequestParam | 获取请求参数(URL 拼接参数、表单提交参数) | GET 请求参数、POST 表单参数(非 JSON) | 可设置 required(是否必填)、defaultValue(默认值) |
| @PathVariable | 获取 URL 路径中的参数(RESTful 风格) | RESTful 接口(如 /user/{id}) | 参数名需与 URL 路径中的占位符一致 |
| @RequestBody | 获取请求体中的 JSON 数据,反序列化为 Java 对象 | POST 请求,前端传递 JSON 数据 | 依赖 HttpMessageConverter,需导入 Jackson 依赖 |
| @ResponseBody | 将 Java 对象序列化为 JSON 数据,返回给前端(不渲染视图) | 前后端分离接口(返回 JSON) | 可与 @Controller 合并为 @RestController(常用) |
| @Controller | 标识当前类为 SpringMVC 的控制器(Controller) | 所有处理请求的 Controller 类 | 若要返回 JSON,需配合 @ResponseBody |
| @RestController | @Controller + @ResponseBody 组合,直接返回 JSON | 前后端分离项目的 Controller 类(最常用) | 无需再单独加 @ResponseBody |
五、全局异常处理:@ControllerAdvice + @ExceptionHandler 实现
核心作用:统一处理所有 Controller 方法抛出的异常,避免每个方法单独捕获异常,简化代码,提升可读性,是实际开发中的标准做法。
1. 核心原理
-
@ControllerAdvice:标识当前类为“全局异常处理类”,Spring 会扫描该类,统一拦截所有 Controller 的异常;
-
@ExceptionHandler:标注在方法上,指定该方法处理的异常类型(如 NullPointerException、Exception);
-
当 Controller 方法抛出异常时,Spring 会找到对应的 @ExceptionHandler 方法,执行异常处理逻辑,返回统一的响应结果。
2. 代码示例(默写专用,可直接复用)
|
|
3. 关键提醒(重点) 🔴
-
@ControllerAdvice 会拦截所有标注 @Controller/@RestController 的类的异常;
-
异常处理方法的优先级:特定异常(如 NullPointerException)> 自定义异常 > 全局异常(Exception);
-
建议结合日志记录异常(如 log.error),方便排查问题;
-
返回统一的响应格式(如 ResultVO),让前端能统一处理异常响应。
总结 🔴
-
SpringMVC 请求流程(10步):浏览器→Tomcat→DispatcherServlet→HandlerMapping→HandlerAdapter→Handler→ModelAndView→ViewResolver→拦截器→浏览器;
-
核心组件职责:DispatcherServlet(总指挥)、HandlerMapping(找方法)、HandlerAdapter(适配执行)、HandlerInterceptor(拦截增强)、ViewResolver(解析视图)、HttpMessageConverter(JSON 序列化);
-
拦截器 vs 过滤器:过滤器是 Servlet 规范,拦截所有请求;拦截器是 Spring 组件,仅拦截 Controller 请求,可注入 Bean;
-
常用注解:@RequestMapping(映射请求)、@RequestParam(获取URL参数)、@PathVariable(RESTful路径参数)、@RequestBody(JSON请求体)、@RestController(返回JSON);
-
全局异常处理:@ControllerAdvice + @ExceptionHandler 实现,统一处理异常,返回统一响应。