Spring MVC核心组件与请求处理流程
Spring MVC请求处理完整流程详解
一、流程文字描述
当一个HTTP请求到达服务器后,会经历以下流程:
-
Filter链处理(入口)
- 请求首先经过Filter链
- 每个Filter按照定义的顺序执行doFilter方法的前置处理
- Filter通过调用chain.doFilter()将请求传递给下一个Filter
-
DispatcherServlet接收请求
- 所有Filter处理完后,请求到达DispatcherServlet
- DispatcherServlet作为前端控制器,统一处理所有请求
-
寻找Handler
- DispatcherServlet调用getHandler方法
- 遍历所有HandlerMapping,找到与当前URL匹配的Handler
- 找到Handler后,把Handler和对应的拦截器封装成HandlerExecutionChain对象
-
获取HandlerAdapter
- 根据Handler的类型,遍历所有HandlerAdapter
- 找到支持该Handler类型的HandlerAdapter
- HandlerAdapter用于调用Handler并处理参数、返回值等
-
拦截器前置处理
- 按顺序调用HandlerExecutionChain中所有拦截器的preHandle方法
- 如果任一拦截器的preHandle返回false,则中断请求处理
- 中断时会触发已执行的拦截器的afterCompletion方法
-
Handler处理请求
- 通过HandlerAdapter调用Handler(Controller方法)
- HandlerAdapter负责参数解析、类型转换
- Handler执行业务逻辑,返回处理结果
-
拦截器后置处理
- Handler执行完成后,按逆序调用所有拦截器的postHandle方法
- 此时视图尚未渲染
-
视图渲染
- 根据Handler返回的结果进行视图渲染
- 如果是@RestController,将返回值转换为JSON/XML等格式
- 如果是传统@Controller,解析视图名称并渲染视图
-
拦截器完成处理
- 视图渲染完成后,按逆序调用所有拦截器的afterCompletion方法
- 无论过程中是否有异常,都会执行afterCompletion
-
Filter链处理(出口)
- 响应会按照与处理请求相反的顺序经过Filter链
- 每个Filter执行doFilter方法的后置处理
- 最终响应返回给客户端
二、关键组件详解
2.1 HandlerMapping
// 核心数据结构
public class RequestMappingHandlerMapping {
// 保存URL与处理器方法的映射关系
private final Map<RequestMappingInfo, HandlerMethod> mappingLookup;
}
// 映射示例
mappingLookup = {
RequestMappingInfo{
patterns=/users/{id}, // URL模式
methods=GET, // HTTP方法
params=[], // 请求参数
headers=[] // 请求头
} -> HandlerMethod{UserController.getUser()}
}
2.2 HandlerExecutionChain
public class HandlerExecutionChain {
// Handler本身(如Controller的方法)
private final Object handler;
// 与Handler关联的拦截器列表
private List<HandlerInterceptor> interceptors;
}
2.3 HandlerAdapter
// 处理@RequestMapping注解的方法
public class RequestMappingHandlerAdapter implements HandlerAdapter {
public ModelAndView handle(request, response, handler) {
// 1. 解析请求参数
Object[] args = resolveParameters(request, handler);
// 2. 调用Controller方法
Object returnValue = invokeMethod(handler, args);
// 3. 处理返回值
return processReturnValue(returnValue);
}
}
2.4 视图渲染
// 1. @RestController(JSON渲染)
@GetMapping("/api/user")
public User getUser() {
return user; // 自动转换为JSON
}
// 2. @Controller(HTML渲染)
@GetMapping("/user")
public String user(Model model) {
model.addAttribute("user", user);
return "userView"; // 解析为具体视图
}
三、拦截器执行流程
3.1 拦截器定义
public class LogInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(request, response, handler) {
System.out.println("LogInterceptor - preHandle");
return true;
}
@Override
public void postHandle(request, response, handler, mv) {
System.out.println("LogInterceptor - postHandle");
}
@Override
public void afterCompletion(request, response, handler, ex) {
System.out.println("LogInterceptor - afterCompletion");
}
}
3.2 执行顺序示例
Filter1 - 请求处理
Filter2 - 请求处理
LogInterceptor - preHandle
SecurityInterceptor - preHandle
Controller方法执行
SecurityInterceptor - postHandle
LogInterceptor - postHandle
视图渲染
SecurityInterceptor - afterCompletion
LogInterceptor - afterCompletion
Filter2 - 响应处理
Filter1 - 响应处理
3.3 拦截器调用过程
// 1. preHandle调用(正序)
for (HandlerInterceptor interceptor : interceptors) {
if (!interceptor.preHandle(request, response, handler)) {
triggerAfterCompletion(request, response, handler, null);
return false;
}
}
// 2. postHandle调用(逆序)
for (int i = interceptors.length - 1; i >= 0; i--) {
interceptors[i].postHandle(requestresponse, handler, mv);
}
// 3. afterCompletion调用(逆序)
for (int i = interceptors.length - 1; i >= 0; i--) {
interceptors[i].afterCompletion(request, response, handler, ex);
}