Skip to content

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: 请求处理流程?

  1. 请求到 DispatcherServlet
  2. HandlerMapping 找到处理器
  3. HandlerAdapter 执行处理器
  4. Controller 处理业务
  5. 返回 ModelAndView
  6. ViewResolver 解析视图
  7. View 渲染页面
  8. 响应

Q3: @Controller 和 @RestController 区别?

  • @Controller:返回视图(String/ModelAndView)
  • @RestController:返回 JSON(= @Controller + @ResponseBody)

Q4: 如何覆盖 Spring MVC 自动配置?

实现 WebMvcConfigurer 接口,或定义同类型 @Bean 覆盖

Q5: 拦截器和过滤器的区别?

对比过滤器拦截器
来源ServletSpring
执行时机DispatcherServlet 之前Controller 前后
用途字符编码、Security权限、日志
注册FilterRegistrationBean实现 WebMvcConfigurer

十、下一章预告

下一章我们将学习 Spring MVC 请求映射与参数绑定

  • @RequestParam / @PathVariable / @RequestBody
  • 复杂对象绑定
  • 自定义参数转换器
  • 文件上传处理

基于 MIT 许可发布