SpringMVC核心流程

SpringMVC 是 Spring 用于 web 开发的模块,基于 Servlet 封装,核心是「前端控制器(DispatcherServlet)」,统一调度所有组件,实现请求的接收、处理、响应全流程。

一、SpringMVC 完整请求处理流程 🔴

核心逻辑:浏览器发起请求 → 前端控制器统一接收 → 组件协同处理 → 后端方法执行 → 响应返回浏览器,共10步。

1. 完整流程 🔴

  1. 浏览器发起 HTTP 请求(如 GET /user/1、POST /user),请求被 web 服务器(如 Tomcat)接收,转发给 SpringMVC 的 DispatcherServlet(前端控制器,所有请求的入口);

  2. DispatcherServlet 接收请求后,调用HandlerMapping(处理器映射器),根据请求 URL 和配置(如 @RequestMapping),找到对应的 Handler(后端控制器,即 Controller 中的方法);

  3. HandlerMapping 返回 Handler 的执行链(包含 Handler 和对应的 HandlerInterceptor 拦截器)给 DispatcherServlet;

  4. DispatcherServlet 调用 HandlerAdapter(处理器适配器),适配当前 Handler(处理参数绑定、JSON 解析等),准备执行 Handler;

  5. 执行 HandlerInterceptor 拦截器的 preHandle 方法(前置拦截,如权限校验,返回 true 则继续,false 则终止);

  6. HandlerAdapter 调用 Handler(后端 Controller 中的目标方法),执行业务逻辑,返回 ModelAndView(包含模型数据和视图名称);

  7. 执行 HandlerInterceptor 拦截器的 postHandle 方法(后置拦截,可修改 ModelAndView,如添加全局数据);

  8. DispatcherServlet 调用 ViewResolver(视图解析器),根据 ModelAndView 中的视图名称,解析出具体的视图(如 JSP、HTML,或 JSON 数据);

  9. 执行 HandlerInterceptor 拦截器的 afterCompletion 方法(完成拦截,如清理资源,无论成功/失败都会执行);

  10. 视图渲染(将模型数据填充到视图中),生成响应结果(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. 代码示例(默写专用,可直接复用)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 全局异常处理类(必须加 @ControllerAdvice)
@ControllerAdvice
@ResponseBody // 返回 JSON 响应(前后端分离场景)
public class GlobalExceptionHandler {

    // 1. 处理特定异常(如空指针异常)
    @ExceptionHandler(NullPointerException.class)
    public ResultVO handleNullPointerException(NullPointerException e) {
        // 日志记录异常(可选)
        log.error("空指针异常:", e);
        // 返回统一响应(自定义 ResultVO 为响应模板)
        return ResultVO.fail(400, "空指针异常:" + e.getMessage());
    }

    // 2. 处理所有异常(兜底,捕获所有未被特定异常处理的异常)
    @ExceptionHandler(Exception.class)
    public ResultVO handleException(Exception e) {
        log.error("系统异常:", e);
        return ResultVO.fail(500, "系统异常,请联系管理员");
    }

    // 3. 处理自定义异常(如业务异常)
    @ExceptionHandler(BusinessException.class)
    public ResultVO handleBusinessException(BusinessException e) {
        log.error("业务异常:", e);
        return ResultVO.fail(e.getCode(), e.getMessage());
    }
}

// 自定义响应模板(ResultVO)
@Data
public class ResultVO {
    private Integer code; // 状态码(200成功,400参数错误,500系统错误)
    private String message; // 提示信息
    private Object data; // 响应数据

    // 静态方法,简化调用
    public static ResultVO fail(Integer code, String message) {
        ResultVO result = new ResultVO();
        result.setCode(code);
        result.setMessage(message);
        return result;
    }
}

3. 关键提醒(重点) 🔴

  • @ControllerAdvice 会拦截所有标注 @Controller/@RestController 的类的异常;

  • 异常处理方法的优先级:特定异常(如 NullPointerException)> 自定义异常 > 全局异常(Exception);

  • 建议结合日志记录异常(如 log.error),方便排查问题;

  • 返回统一的响应格式(如 ResultVO),让前端能统一处理异常响应。

总结 🔴

  1. SpringMVC 请求流程(10步):浏览器→Tomcat→DispatcherServlet→HandlerMapping→HandlerAdapter→Handler→ModelAndView→ViewResolver→拦截器→浏览器;

  2. 核心组件职责:DispatcherServlet(总指挥)、HandlerMapping(找方法)、HandlerAdapter(适配执行)、HandlerInterceptor(拦截增强)、ViewResolver(解析视图)、HttpMessageConverter(JSON 序列化);

  3. 拦截器 vs 过滤器:过滤器是 Servlet 规范,拦截所有请求;拦截器是 Spring 组件,仅拦截 Controller 请求,可注入 Bean;

  4. 常用注解:@RequestMapping(映射请求)、@RequestParam(获取URL参数)、@PathVariable(RESTful路径参数)、@RequestBody(JSON请求体)、@RestController(返回JSON);

  5. 全局异常处理:@ControllerAdvice + @ExceptionHandler 实现,统一处理异常,返回统一响应。