Spring MVC 中请求处理流程及核心组件解析

在 Spring MVC 中,请求从客户端发送到服务器后,需要经过一系列组件的处理才能最终到达具体的 Controller 方法。这个过程涉及多个核心组件和复杂的映射机制,下面详细解析其工作流程:

1. 核心组件与请求流程

Spring MVC 的请求处理流程主要涉及以下核心组件:

DispatcherServlet:前端控制器,接收所有 HTTP 请求,是整个请求处理的入口。

HandlerMapping:请求映射处理器,负责将请求 URL 映射到对应的 Handler(即 Controller 方法)。

HandlerAdapter:处理器适配器,将不同类型的 Handler 统一为可执行的接口。

Controller:具体的业务控制器,处理请求并返回 ModelAndView。

ViewResolver:视图解析器,将逻辑视图名解析为具体的 View 对象。

View:视图对象,负责将模型数据渲染到客户端。

请求处理流程

typescript 复制代码
客户端请求 → DispatcherServlet → HandlerMapping → HandlerAdapter →

Controller → ModelAndView → ViewResolver → View → 响应客户端

2. HandlerMapping 的请求映射机制

HandlerMapping 是实现 URL 到 Controller 方法映射的核心组件,Spring MVC 提供了多种实现:

RequestMappingHandlerMapping :处理 @RequestMapping 注解的映射(最常用)。

BeanNameUrlHandlerMapping :根据 Bean 名称映射请求(如 /hellohelloController Bean)。

SimpleUrlHandlerMapping:通过配置文件手动指定 URL 与 Handler 的映射关系。

基于注解的映射流程

当使用 @RequestMapping 或其派生注解(如 @GetMapping)时:

启动时扫描 :Spring MVC 在启动时会扫描所有带有 @Controller@RestController 注解的 Bean。

解析方法映射 :提取这些 Bean 中所有标注了 @RequestMapping 的方法,构建映射关系。

生成 HandlerMethod 对象 :将每个映射方法封装为 HandlerMethod 对象,包含控制器实例、方法反射信息和请求匹配条件(如 URL、请求方法、请求参数等)。

注册到映射器 :将 HandlerMethod 对象注册到 RequestMappingHandlerMapping 的内部映射表中。

3. DispatcherServlet 的请求分发

当接收到请求时,DispatcherServlet 会按以下步骤处理:

获取 HandlerExecutionChain

java 复制代码
HandlerExecutionChain handler = getHandler(request);

DispatcherServlet 调用 HandlerMappinggetHandler(request) 方法,根据请求 URL 查找匹配的 Handler。

HandlerMapping 返回一个 HandlerExecutionChain 对象,包含 Handler(即 Controller 方法)和相关的拦截器(Interceptor)。

获取 HandlerAdapter

java 复制代码
HandlerAdapter ha = getHandlerAdapter(handler.getHandler());

DispatcherServlet 根据 Handler 的类型,从已注册的 HandlerAdapter 中选择合适的适配器。

例如,RequestMappingHandlerAdapter 用于处理基于注解的 Controller 方法。

执行 Handler

java 复制代码
ModelAndView mv = ha.handle(request, response, handler.getHandler());

HandlerAdapter 调用 Controller 方法,并传递请求参数,获取返回的 ModelAndView

4. 参数解析与返回值处理

参数解析

HandlerAdapter 通过 HandlerMethodArgumentResolver 解析请求参数:

内置解析器:Spring MVC 提供多种解析器,例如:

RequestParamMethodArgumentResolver:解析 @RequestParam 注解的参数。

PathVariableMethodArgumentResolver:解析路径变量(如 /users/{id})。

RequestBodyArgumentResolver:解析请求体(如 JSON、XML),需配合 @RequestBody 注解。

自定义解析器 :可实现 HandlerMethodArgumentResolver 接口自定义参数解析逻辑。

返回值处理

HandlerAdapter 通过 HandlerMethodReturnValueHandler 处理返回值:

内置处理器:例如:

ViewNameMethodReturnValueHandler:处理返回视图名的方法。

ModelAndViewMethodReturnValueHandler:处理返回 ModelAndView 的方法。

ResponseBodyEmitterReturnValueHandler:处理异步返回值(如 ResponseEntity)。

@ResponseBody 注解 :若方法标注了 @ResponseBody,则通过 HttpMessageConverter 将返回值序列化为响应体(如 JSON)。

5. 示例:从请求到 Controller 的完整流程

假设存在以下 Controller:

java 复制代码
@RestController

@RequestMapping("/api/users")

public class UserController {

   @Autowired

   private UserService userService;

   @GetMapping("/{id}")

   public UserDTO getUser(@PathVariable Long id) {

       return userService.getUserById(id);

   }

}

请求流程

客户端发送请求 GET /api/users/123

DispatcherServlet 接收请求,调用 RequestMappingHandlerMapping

HandlerMapping 根据 URL /api/users/123 和请求方法 GET,匹配到 UserController.getUser() 方法。

DispatcherServlet 获取 HandlerAdapter(即 RequestMappingHandlerAdapter)。

HandlerAdapter 解析路径变量 id=123,并调用 UserController.getUser(123)

Controller 方法返回 UserDTO 对象。

由于 @RestController 隐含 @ResponseBody,HandlerAdapter 通过 HttpMessageConverterUserDTO 序列化为 JSON。

DispatcherServlet 将 JSON 响应返回给客户端。

6. 拦截器与异常处理

拦截器(Interceptor)

在请求到达 Controller 前后,可通过拦截器执行额外逻辑:

实现 HandlerInterceptor 接口

java 复制代码
public class LoggingInterceptor implements HandlerInterceptor {

   @Override

   public boolean preHandle(HttpServletRequest request,

                           HttpServletResponse response,

                           Object handler) {

       // 请求处理前执行(如日志记录、权限校验)

       return true; // 继续执行后续流程

   }

  

   @Override

   public void postHandle(HttpServletRequest request,

                         HttpServletResponse response,

                         Object handler,

                         ModelAndView modelAndView) {

       // 请求处理后、视图渲染前执行

   }

  

   @Override

   public void afterCompletion(HttpServletRequest request,

                               HttpServletResponse response,

                               Object handler,

                               Exception ex) {

       // 完成请求处理(如资源清理)

   }

}

注册拦截器

java 复制代码
@Configuration

public class WebConfig implements WebMvcConfigurer {

   @Override

   public void addInterceptors(InterceptorRegistry registry) {

       registry.addInterceptor(new LoggingInterceptor())

               .addPathPatterns("/api/**"); // 拦截所有 API 请求

   }

}
异常处理

通过 @ControllerAdvice@ExceptionHandler 统一处理异常:

java 复制代码
@ControllerAdvice

public class GlobalExceptionHandler {

   @ExceptionHandler(NotFoundException.class)

   public ResponseEntity<String> handleNotFoundException(NotFoundException ex) {

       return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());

   }

}

总结

Spring MVC 通过 HandlerMapping 实现 URL 到 Controller 方法的映射,通过 HandlerAdapter 统一调用不同类型的 Handler,并借助 参数解析器返回值处理器 完成请求参数和响应数据的转换。整个过程由 DispatcherServlet 协调,配合拦截器和异常处理机制,形成了一个完整的请求处理体系。理解这些机制,有助于更高效地开发和调试 Spring MVC 应用。

相关推荐
wasp5204 小时前
做了技术管理后,我发现技术和管理其实可以兼得
java·运维·网络
MarkHD4 小时前
车辆TBOX科普 第45次
java·开发语言
okseekw4 小时前
字面量的初步认识
java
倚肆5 小时前
Spring Boot CORS 配置详解:CorsConfigurationSource 全面指南
java·spring boot·后端
q***72195 小时前
Spring Boot(快速上手)
java·spring boot·后端
CoderYanger5 小时前
C.滑动窗口——1423. 可获得的最大点数
java·开发语言·算法·leetcode·1024程序员节
Swift社区5 小时前
StackOverflowError 栈溢出的原因与实战解决方案
java·spring boot·spring
字节拾光录5 小时前
手机号存储避坑指南:从20亿级数据库实践看,为什么VARCHAR才是终极答案
java·数据库·oracle
p***97615 小时前
SpringBoot(7)-Swagger
java·spring boot·后端
j***29486 小时前
springboot集成onlyoffice(部署+开发)
java·spring boot·后端