Spring MVC核心流程深度解析:从请求到响应的完美掌控

Spring MVC 核心流程深度解析:从请求到响应的完美掌控

Spring MVC 是 Spring 框架中处理 Web 请求的核心模块,基于 Model-View-Controller (MVC) 设计模式。它以 DispatcherServlet 为入口,实现从 HTTP 请求到响应的完整生命周期管理。下面从最实用的角度(基于 Spring Boot 2.x/3.x 和 Spring MVC 5.x/6.x)来深度剖析其核心流程,帮助你建立清晰的思维框架。

目标:看完后,你能自信地说“我能掌控 Spring MVC 的请求响应全链路”,并能调试/优化 90% 的 Web 项目问题。

第一步:核心理念与整体架构(先建立大局观)

Spring MVC 的本质是一个前端控制器(Front Controller)模式

  • DispatcherServlet 是总入口,负责分发所有请求。
  • 流程像一个“流水线”:请求进来 → 匹配处理器 → 执行逻辑 → 渲染视图 → 返回响应。
  • 关键原则:松耦合、可扩展(通过接口/注解自定义组件)。

整体流程图(文本简化版):

HTTP Request → DispatcherServlet (入口)
              ↓
HandlerMapping (匹配 Controller/Method)
              ↓
HandlerInterceptor (前置拦截)
              ↓
HandlerAdapter (执行 Handler)
              ↓
ModelAndView / ResponseBody (处理结果)
              ↓
ViewResolver (视图解析)
              ↓
HandlerInterceptor (后置/完成拦截)
              ↓
HTTP Response

异常处理:任何步骤出错 → HandlerExceptionResolver → 统一响应。

第二步:核心组件速览(嵌入式/企业级最常用)

组件名称作用默认实现/注解支持扩展点
DispatcherServlet总调度器,初始化所有组件Spring Boot 自动配置web.xml 或 ServletRegistrationBean
HandlerMapping映射请求到 Handler (Controller 方法)RequestMappingHandlerMapping (@RequestMapping)自定义 Mapping
HandlerAdapter执行 Handler,返回 ModelAndViewRequestMappingHandlerAdapter (@ControllerAdvice)支持 REST/注解
ViewResolver解析视图名到实际 ViewInternalResourceViewResolver (JSP/Thymeleaf)多视图支持
HandlerInterceptor拦截器(AOP 式钩子)— (@Interceptor 或实现接口)权限/日志
HandlerExceptionResolver异常处理器DefaultHandlerExceptionResolver (@ExceptionHandler)全局异常
MultipartResolver文件上传解析StandardServletMultipartResolver

提示:在 Spring Boot 中,这些组件大多自动装配,但你可以用 @Bean 自定义。

第三步:从请求到响应的详细流程拆解(步步追踪)

假设一个典型请求:GET /user/1(注解式 Controller)。

  1. 请求进入 DispatcherServlet
  • Tomcat/Nettys 等容器转发请求到 DispatcherServlet 的 doService() 方法。
  • 初始化:Servlet 初始化时加载 Spring 上下文(WebApplicationContext),注册所有组件。
  • 代码追踪:FrameworkServlet.doGet() → DispatcherServlet.doDispatch()(核心分发方法)。
  1. HandlerMapping 匹配 Handler
  • 遍历所有 HandlerMapping(如 RequestMappingHandlerMapping),根据 URL、Method、Header 等匹配 @RequestMapping 方法。
  • 返回 HandlerExecutionChain(包含 Handler + Interceptors)。
  • 示例:@GetMapping("/user/{id}") public User getUser(@PathVariable Long id) { ... }
  • 坑:多 Mapping 时,按顺序匹配(可自定义顺序)。
  1. 应用前置拦截器 (preHandle)
  • 执行链中所有 Interceptor 的 preHandle():如权限检查、日志。
  • 如果返回 false,流程中断(直接响应)。
  1. HandlerAdapter 执行 Handler
  • Adapter(如 RequestMappingHandlerAdapter)调用 Controller 方法。
  • 参数解析:@PathVariable、@RequestParam、@RequestBody 等(通过 ArgumentResolvers)。
  • 返回值:ModelAndView(视图+模型)或 @ResponseBody(JSON 等)。
  • 代码示例:
    java @Controller public class UserController { @GetMapping("/user/{id}") public ModelAndView getUser(@PathVariable Long id) { User user = userService.findById(id); // 业务逻辑 ModelAndView mav = new ModelAndView("userDetail"); // 视图名 mav.addObject("user", user); // 模型数据 return mav; } }
    或 REST 式:
    java @RestController public class UserController { @GetMapping("/user/{id}") public User getUser(@PathVariable Long id) { return userService.findById(id); // 自动转 JSON } }
  1. 处理返回结果
  • 如果是 ModelAndView:收集模型数据。
  • 如果是 @ResponseBody:用 HttpMessageConverters(如 MappingJackson2HttpMessageConverter)转 JSON/XML。
  1. ViewResolver 解析视图
  • 根据视图名(如 “userDetail”)解析成 View(如 JSP、Thymeleaf)。
  • 示例配置(application.yml):
    yaml spring: thymeleaf: prefix: classpath:/templates/ suffix: .html
  • 渲染:View.render() 合并模型数据生成 HTML。
  1. 应用后置/完成拦截器 (postHandle / afterCompletion)
  • postHandle:视图渲染前(如修改模型)。
  • afterCompletion:响应后(如清理资源),无论成功/失败都执行。
  1. 返回响应
  • DispatcherServlet 写回 HttpServletResponse(状态码、Header、Body)。
  • 结束:请求响应完成。

异常分支:任何步骤抛异常 → HandlerExceptionResolver(如 @ExceptionHandler 方法)处理 → 返回错误视图/JSON。

第四步:真实代码示例(Spring Boot 风格,强烈建议敲一遍)

最小项目结构

  • pom.xml:spring-boot-starter-web
  • Application.java:@SpringBootApplication

Controller 示例(见上)。

自定义拦截器(日志示例):

@Component
public class LogInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        log.info("Request URL: {}", request.getRequestURL());
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        log.info("Response Status: {}", response.getStatus());
    }
}

注册:@Configuration 类中 addInterceptors()。

全局异常处理

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public ModelAndView handleException(Exception ex) {
        ModelAndView mav = new ModelAndView("error");
        mav.addObject("message", ex.getMessage());
        return mav;
    }
}

第五步:最容易踩的 8 个坑与优化(企业级经验)

  1. 性能瓶颈:DispatcherServlet 是单线程入口,用线程池/异步 (@EnableAsync) 优化。
  2. 参数绑定失败:自定义 Converter/Formatter。
  3. CORS/安全性:用 @CrossOrigin 或 WebSecurityConfigurer。
  4. 视图解析冲突:多 ViewResolver 时,按优先级。
  5. 文件上传大小限:multipart.max-file-size 配置。
  6. REST vs MVC:@RestController = @Controller + @ResponseBody。
  7. 测试:用 MockMvc 测试全流程(@WebMvcTest)。
  8. 版本差异:Spring 6.x 支持 Jakarta EE(Servlet 5.0+),迁移时注意包名。

第六步:快速自测清单(验证掌握度)

  1. DispatcherServlet 的核心方法是什么?(doDispatch)
  2. HandlerMapping 如何支持注解?(@RequestMapping)
  3. 返回 String 类型时,ViewResolver 如何工作?(视为视图名)
  4. 如何处理 JSON 返回?(@ResponseBody + Jackson)
  5. 拦截器 preHandle 返回 false 会怎样?(中断流程)
  6. 异常如何统一处理?(@ControllerAdvice + @ExceptionHandler)
  7. 文件上传用什么组件?(MultipartResolver)
  8. 如何异步处理请求?(Callable / DeferredResult)

答案自己验证(可查 Spring 官方文档)。如果你把流程图画一遍、代码跑通,恭喜——Spring MVC 核心你已掌控

有哪部分模糊(如异步 Servlet、WebFlux 对比、源码调试、性能调优)?直接告诉我,我再针对性展开。

文章已创建 4026

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部