Spring MVC 处理流程
一、Spring MVC 架构
┌─────────────────────────────────────────────────────────────────┐
│ Spring MVC 请求处理流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 浏览器 ──▶ DispatcherServlet (前端控制器) │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ HandlerMapping │ ← 处理器映射 │
│ │ (找出处理器) │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ HandlerAdapter │ ← 处理器适配器 │
│ │ (执行处理器) │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Controller │ ← 控制器(业务逻辑) │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ ViewResolver │ ← 视图解析器 │
│ │ (解析视图) │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ 视图渲染 │
│ │ │
│ ▼ │
│ 响应给浏览器 │
│ │
└─────────────────────────────────────────────────────────────────┘二、核心组件
1. DispatcherServlet(前端控制器)
java
// Spring Boot 自动配置
// org.springframework.web.servlet.DispatcherServlet
// 默认映射:/
public class DispatcherServlet extends HttpServlet {
// 处理请求入口
protected void doDispatch(HttpServletRequest request,
HttpServletResponse response) {
// 1. 找到处理器
HandlerExecutionChain handler = getHandler(processedRequest);
// 2. 找到适配器
HandlerAdapter ha = getHandlerAdapter(handler.getHandler());
// 3. 执行预处理
if (!handler.applyPreHandle(request, response)) {
return;
}
// 4. 执行处理器(调用 Controller)
mv = ha.handle(processedRequest, response, handler.getHandler());
// 5. 执行后处理
handler.applyPostHandle(request, response, mv);
// 6. 处理结果(渲染视图)
processDispatchResult(request, response, mv);
}
}2. HandlerMapping(处理器映射)
java
// 请求 URL → Controller 方法的映射
// 常用实现:
// 1. RequestMappingHandlerMapping
// 处理 @RequestMapping 注解
// 2. BeanNameUrlHandlerMapping
// 处理 Controller 名称映射到 URL
// 3. SimpleUrlHandlerMapping
// 手动配置 URL 映射
// 4. ControllerClassNameHandlerMapping
// 类名自动映射
// HelloController → /hello/*3. HandlerAdapter(处理器适配器)
java
// 适配不同类型的处理器
// 常用实现:
// 1. RequestMappingHandlerAdapter
// 执行 @RequestMapping 标注的方法
// 2. HttpRequestHandlerAdapter
// 执行 HttpRequestHandler
// 3. SimpleControllerHandlerAdapter
// 执行 Controller 接口实现类
// 4. AnnotationMethodHandlerAdapter(已废弃)4. ViewResolver(视图解析器)
java
// 视图名 → 实际视图对象
// 常用实现:
// 1. InternalResourceViewResolver
// 解析 JSP 视图
// 2. ThymeleafViewResolver
// 解析 Thymeleaf 模板
// 3. FreeMarkerViewResolver
// 解析 FreeMarker 模板
// 4. JsonViewResolver
// 返回 JSON 视图5. HandlerExceptionResolver(异常处理)
java
// 异常 → 错误页面/错误响应
// 实现:
// 1. SimpleMappingExceptionResolver
// 映射异常到视图
// 2. DefaultHandlerExceptionResolver
// Spring MVC 标准异常处理
// 3. ResponseStatusExceptionResolver
// 处理 @ResponseStatus 异常
// 4. ExceptionHandlerExceptionResolver
// 处理 @ExceptionHandler 方法三、请求完整处理流程
┌─────────────────────────────────────────────────────────────────────┐
│ 完整请求处理流程 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. 请求进入 DispatcherServlet.doDispatch() │
│ │
│ 2. HandlerMapping 查找处理器 │
│ └─▶ RequestMappingHandlerMapping.getHandler() │
│ └─▶ 返回 HandlerExecutionChain (handler + interceptors) │
│ │
│ 3. HandlerAdapter 选择适配器 │
│ └─▶ RequestMappingHandlerAdapter │
│ │
│ 4. 前置拦截器 preHandle() │
│ └─▶ 返回 false 则中断流程 │
│ │
│ 5. 适配器执行处理器 │
│ └─▶ HandlerAdapter.handle() │
│ └─▶ 执行 Controller 方法,返回 ModelAndView │
│ │
│ 6. 后置拦截器 postHandle() │
│ │
│ 7. 异常检测 │
│ └─▶ 若有异常,交给 HandlerExceptionResolver 处理 │
│ │
│ 8. 视图解析 │
│ └─▶ ViewResolver 解析视图名 │
│ │
│ 9. 视图渲染 │
│ └─▶ View.render() 合并 Model 渲染页面 │
│ │
│ 10. 后置拦截器 afterCompletion() │
│ │
│ 11. 响应给客户端 │
│ │
└─────────────────────────────────────────────────────────────────────┘四、九大组件初始化
DispatcherServlet 初始化
java
// org.springframework.web.servlet.DispatcherServlet
//initStrategies()
protected void initStrategies(ApplicationContext context) {
// 1. multipart 解析器(文件上传)
initMultipartResolver(context);
// 2. 国际化解析器
initLocaleResolver(context);
// 3. 主题解析器
initThemeResolver(context);
// 4. 处理器映射
initHandlerMappings(context);
// 5. 处理器适配器
initHandlerAdapters(context);
// 6. 处理器异常解析器
initHandlerExceptionResolvers(context);
// 7. 请求到视图名转换器
initRequestToViewNameTranslator(context);
// 8. 视图解析器
initViewResolvers(context);
// 9. FlashMap 管理器
initFlashMapManager(context);
}组件查找策略
java
// 以 HandlerMapping 为例
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
// 1. 先从容器中找所有 HandlerMapping 类型的 Bean
if (detectAllHandlerMappings) {
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context,
HandlerMapping.class, true, false);
// 排序
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
OrderComparator.sort(this.handlerMappings);
}
}
// 2. 否则使用默认策略
else {
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME,
HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) { }
}
// 3. 如果都没有,创建默认实现
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
}
}五、Spring Boot 自动配置
WebMvcAutoConfiguration
java
// Spring Boot 自动配置 MVC
@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(View.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
public class WebMvcAutoConfiguration {
// 配置 HandlerMapping
@Bean
@ConditionalOnBean(ViewResolver.class)
@ConditionalOnMissingBean(name = "viewResolver")
public BeanNameViewResolver beanNameViewResolver() {
return new BeanNameViewResolver();
}
// 配置视图解析器
@Bean
@ConditionalOnMissingBean(ViewResolver.class)
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}覆盖默认配置
java
// 方式1:实现 WebMvcConfigurer
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api/login");
}
}
// 方式2:@Bean 定义组件(优先级更高)
@Configuration
public class WebConfig {
@Bean
public ViewResolver myViewResolver() {
return new MyViewResolver();
}
}六、Spring MVC 注解
@RequestMapping
java
// 类级别
@RestController
@RequestMapping("/api/users")
public class UserController {
// 方法级别
@RequestMapping(
value = "/{id}", // URL 路径
method = RequestMethod.GET, // HTTP 方法
params = "action=view", // 请求参数条件
headers = "X-Custom-Header", // 请求头条件
consumes = "application/json", // 消费内容类型
produces = "application/json" // 生产内容类型
)
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}
// 衍生注解(更简洁)
@GetMapping // 等价于 @RequestMapping(method = GET)
@PostMapping // POST
@PutMapping // PUT
@DeleteMapping // DELETE
@PatchMapping // PATCH七、Controller 返回值
返回类型
java
@RestController
public class ReturnController {
// 1. 返回对象(JSON)
@GetMapping("/obj")
public User getUser() {
return new User("张三", 18);
}
// 2. 返回 ResponseEntity
@GetMapping("/entity")
public ResponseEntity<User> getUserEntity() {
return ResponseEntity.ok(new User("张三", 18));
}
// 3. 返回 Map
@GetMapping("/map")
public Map<String, Object> getMap() {
return Map.of("name", "张三", "age", 18);
}
// 4. 返回 List
@GetMapping("/list")
public List<User> getUsers() {
return List.of(new User("张三", 18), new User("李四", 20));
}
// 5. 返回 void(通过 HttpServletResponse)
@GetMapping("/raw")
public void getRaw(HttpServletResponse response) throws IOException {
response.getWriter().write("raw data");
}
// 6. 返回字符串(视图名)
@GetMapping("/view")
public String getView() {
return "user-detail"; // 视图名
}
}@ResponseBody
java
// 标记返回值为响应体(不经过视图解析)
@RestController
public class JsonController {
@ResponseBody // 返回 JSON(需要 Jackson)
@GetMapping("/json")
public User getUser() {
return new User("张三", 18);
}
// @RestController 相当于 @Controller + @ResponseBody
}
// 或者在类上标注 @Controller + 方法上标注 @ResponseBody
@Controller
public class JsonController {
@ResponseBody
@GetMapping("/json")
public User getUser() {
return new User("张三", 18);
}
}八、请求流程时序图
┌────────┐ ┌───────────────────┐ ┌───────────────────┐
│ Browser│ │ DispatcherServlet │ │ HandlerMapping │
└───┬────┘ └─────────┬─────────┘ └─────────┬─────────┘
│ │ │
│ 1.请求 │ │
│───────────────────▶│ │
│ │ 2.getHandler() │
│ │─────────────────────▶│
│ │◀─────────────────────│
│ │ HandlerExecutionChain
│ │ │
│ │ 3.getHandlerAdapter() │
│ │─────────────────────▶│
│ │◀─────────────────────│
│ │ HandlerAdapter │
│ │ │
│ │ 4.preHandle() │
│ │───────────────────────│
│ │◀──────────────────────│
│ │ │
│ │ 5.handle() │
│ │───────────────────────│
│ │◀──────────────────────│
│ │ ModelAndView │
│ │ │
│ │ 6.postHandle() │
│ │───────────────────────│
│ │◀──────────────────────│
│ │ │
│ │ 7.render() │
│ │───────────────────────│
│ │ │
│ 8.响应 │ │
│◀──────────────────│ │
│ │ │九、面试高频问题
Q1: Spring MVC 的核心组件?
- DispatcherServlet(前端控制器)
- HandlerMapping(处理器映射)
- HandlerAdapter(处理器适配器)
- Controller(控制器)
- ViewResolver(视图解析器)
- HandlerExceptionResolver(异常处理)
Q2: 请求处理流程?
- 请求到 DispatcherServlet
- HandlerMapping 找到处理器
- HandlerAdapter 执行处理器
- Controller 处理业务
- 返回 ModelAndView
- ViewResolver 解析视图
- View 渲染页面
- 响应
Q3: @Controller 和 @RestController 区别?
@Controller:返回视图(String/ModelAndView)@RestController:返回 JSON(= @Controller + @ResponseBody)
Q4: 如何覆盖 Spring MVC 自动配置?
实现 WebMvcConfigurer 接口,或定义同类型 @Bean 覆盖
Q5: 拦截器和过滤器的区别?
| 对比 | 过滤器 | 拦截器 |
|---|---|---|
| 来源 | Servlet | Spring |
| 执行时机 | DispatcherServlet 之前 | Controller 前后 |
| 用途 | 字符编码、Security | 权限、日志 |
| 注册 | FilterRegistrationBean | 实现 WebMvcConfigurer |
十、下一章预告
下一章我们将学习 Spring MVC 请求映射与参数绑定:
- @RequestParam / @PathVariable / @RequestBody
- 复杂对象绑定
- 自定义参数转换器
- 文件上传处理