一句话总结
Spring MVC 执行流程核心:DispatcherServlet 作为前端控制器统一调度。流程:请求 → DispatcherServlet → HandlerMapping(找到处理器)→ HandlerAdapter(执行处理器)→ Controller 处理 → 返回 ModelAndView → ViewResolver(解析视图)→ 渲染响应。关键组件:HandlerMapping(URL 映射到 Controller)、HandlerAdapter(适配不同类型的 Controller)、HandlerInterceptor(拦截器链,前置 → Controller → 后置 → 完成)、ViewResolver(逻辑视图名 → 物理视图)。
初级理解
执行流程概览
# Spring MVC 请求处理流程
# 1. 用户发送请求 → DispatcherServlet(前端控制器)
# 2. DispatcherServlet 调用 HandlerMapping
# 3. HandlerMapping 返回 HandlerExecutionChain(Handler + 拦截器)
# 4. DispatcherServlet 调用 HandlerAdapter
# 5. HandlerAdapter 执行 Handler(Controller)
# 6. Controller 返回 ModelAndView
# 7. DispatcherServlet 调用 ViewResolver
# 8. ViewResolver 返回 View
# 9. View 渲染,返回响应
# 核心组件
# DispatcherServlet:前端控制器,统一调度
# HandlerMapping:处理器映射,URL → Controller
# HandlerAdapter:处理器适配器,适配不同类型的 Controller
# HandlerInterceptor:拦截器
# ViewResolver:视图解析器
# View:视图
中级深入
DispatcherServlet 源码分析
# DispatcherServlet.doDispatch() 核心源码
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
try {
// 1. 文件上传处理
processedRequest = checkMultipart(request);
// 2. 获取 Handler(通过 HandlerMapping)
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 3. 获取 HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 4. 执行拦截器 preHandle
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return; // 拦截器返回 false,停止
}
// 5. 执行 Handler(Controller 方法)
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 6. 执行拦截器 postHandle
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 7. 处理视图
processDispatchResult(processedRequest, response, mappedHandler, mv);
} finally {
// 8. 执行拦截器 afterCompletion
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
拦截器 vs 过滤器
| 对比维度 | 拦截器(Interceptor) | 过滤器(Filter) |
| 归属 | Spring MVC | Servlet 容器 |
| 执行顺序 | Filter → Interceptor | 先于 Interceptor |
| 能力 | 可获取 Controller、参数 | 只能获取 Request/Response |
| 适用场景 | 权限、日志(业务相关) | 编码、跨域(通用) |
高级拓展
HandlerMapping 和 HandlerAdapter
# HandlerMapping 实现类
# RequestMappingHandlerMapping:处理 @RequestMapping 注解
# BeanNameUrlHandlerMapping:处理 Bean name 以 "/" 开头的
# SimpleUrlHandlerMapping:直接配置 URL 映射
# HandlerAdapter 实现类
# RequestMappingHandlerAdapter:处理 @RequestMapping 方法
# HttpRequestHandlerAdapter:处理 HttpRequestHandler
# SimpleControllerHandlerAdapter:处理 Controller 接口
# 为什么需要 HandlerAdapter?
# 不同类型的 Controller 执行方式不同
# 通过适配器模式统一调用
@ResponseBody 和 @RestController
# @ResponseBody 原理
# 1. Controller 方法标注 @ResponseBody
# 2. 返回值不走视图解析
# 3. 通过 HttpMessageConverter 将返回值写入 Response Body
# 4. 默认使用 Jackson 将对象转为 JSON
# @RestController = @Controller + @ResponseBody
@RestController
public class UserController {
@GetMapping("/user/{id}")
public User getUser(@PathVariable Long id) {
return userService.getById(id); // 自动转 JSON
}
}
# HttpMessageConverter 常用实现
# MappingJackson2HttpMessageConverter:JSON 转换
# StringHttpMessageConverter:字符串转换
# ByteArrayHttpMessageConverter:字节数组转换
实战场景
场景:自定义拦截器
# 1. 定义拦截器
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
String token = request.getHeader("Authorization");
if (token == null) {
response.setStatus(401);
return false; // 拦截
}
return true; // 放行
}
}
# 2. 注册拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**") // 拦截路径
.excludePathPatterns("/api/login"); // 排除路径
}
}
面试模拟
面试官:Spring MVC 的执行流程是怎样的?
你:DispatcherServlet 接收请求 → HandlerMapping 找到 Handler → HandlerAdapter 执行 Handler → Controller 返回 ModelAndView → ViewResolver 解析视图 → 渲染响应。拦截器在 Handler 前后执行(preHandle → Controller → postHandle → afterCompletion)。
面试官:拦截器和过滤器有什么区别?
你:过滤器是 Servlet 容器层面的,先于拦截器执行,只能获取 Request/Response;拦截器是 Spring MVC 层面的,可以获取 Controller 和方法参数。过滤器适合编码、跨域等通用处理,拦截器适合权限、日志等业务处理。