在 Spring MVC 中,请求从客户端发送到服务器后,需要经过一系列组件的处理才能最终到达具体的 Controller 方法。这个过程涉及多个核心组件和复杂的映射机制,下面详细解析其工作流程:
1. 核心组件与请求流程
Spring MVC 的请求处理流程主要涉及以下核心组件:
DispatcherServlet:前端控制器,接收所有 HTTP 请求,是整个请求处理的入口。
HandlerMapping:请求映射处理器,负责将请求 URL 映射到对应的 Handler(即 Controller 方法)。
HandlerAdapter:处理器适配器,将不同类型的 Handler 统一为可执行的接口。
Controller:具体的业务控制器,处理请求并返回 ModelAndView。
ViewResolver:视图解析器,将逻辑视图名解析为具体的 View 对象。
View:视图对象,负责将模型数据渲染到客户端。
请求处理流程:
客户端请求 → DispatcherServlet → HandlerMapping → HandlerAdapter →Controller → ModelAndView → ViewResolver → View → 响应客户端
2. HandlerMapping 的请求映射机制
HandlerMapping 是实现 URL 到 Controller 方法映射的核心组件,Spring MVC 提供了多种实现:
RequestMappingHandlerMapping:处理 @RequestMapping
注解的映射(最常用)。
BeanNameUrlHandlerMapping:根据 Bean 名称映射请求(如 /hello
→ helloController
Bean)。
SimpleUrlHandlerMapping:通过配置文件手动指定 URL 与 Handler 的映射关系。
基于注解的映射流程
当使用 @RequestMapping
或其派生注解(如 @GetMapping
)时:
启动时扫描:Spring MVC 在启动时会扫描所有带有 @Controller
或 @RestController
注解的 Bean。
解析方法映射:提取这些 Bean 中所有标注了 @RequestMapping
的方法,构建映射关系。
生成 HandlerMethod 对象:将每个映射方法封装为 HandlerMethod
对象,包含控制器实例、方法反射信息和请求匹配条件(如 URL、请求方法、请求参数等)。
注册到映射器:将 HandlerMethod
对象注册到 RequestMappingHandlerMapping
的内部映射表中。
3. DispatcherServlet 的请求分发
当接收到请求时,DispatcherServlet
会按以下步骤处理:
获取 HandlerExecutionChain:
HandlerExecutionChain handler = getHandler(request);
DispatcherServlet 调用 HandlerMapping
的 getHandler(request)
方法,根据请求 URL 查找匹配的 Handler。
HandlerMapping 返回一个 HandlerExecutionChain
对象,包含 Handler(即 Controller 方法)和相关的拦截器(Interceptor)。
获取 HandlerAdapter:
HandlerAdapter ha = getHandlerAdapter(handler.getHandler());
DispatcherServlet 根据 Handler 的类型,从已注册的 HandlerAdapter
中选择合适的适配器。
例如,RequestMappingHandlerAdapter
用于处理基于注解的 Controller 方法。
执行 Handler:
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:
@RestController@RequestMapping("/api/users")public class UserController {@Autowiredprivate 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 通过 HttpMessageConverter
将 UserDTO
序列化为 JSON。
DispatcherServlet 将 JSON 响应返回给客户端。
6. 拦截器与异常处理
拦截器(Interceptor)
在请求到达 Controller 前后,可通过拦截器执行额外逻辑:
实现 HandlerInterceptor
接口:
public class LoggingInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) {// 请求处理前执行(如日志记录、权限校验)return true; // 继续执行后续流程}@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView) {// 请求处理后、视图渲染前执行}@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) {// 完成请求处理(如资源清理)}}
注册拦截器:
@Configurationpublic class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoggingInterceptor()).addPathPatterns("/api/**"); // 拦截所有 API 请求}}
异常处理
通过 @ControllerAdvice
和 @ExceptionHandler
统一处理异常:
@ControllerAdvicepublic 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 应用。