Skip to content

Spring MVC 详解

  Spring MVC 是 Spring 框架的 Web 模块,基于 MVC 设计模式,通过 DispatcherServlet 作为前端控制器统一调度请求。

一、MVC 架构

MVC 三层角色:

  Model(模型):
    数据 + 业务逻辑
    Service + Dao + Entity

  View(视图):
    展示层
    JSP / Thymeleaf / JSON(前后端分离)

  Controller(控制器):
    请求入口,协调 Model 和 View
    @Controller / @RestController

二、DispatcherServlet 核心架构

Spring MVC 请求处理流程:

  客户端请求


  ┌─────────────────────────────────────────────────────────────┐
  │ ① DispatcherServlet(前端控制器)                            │
  │   所有请求的入口,统一分发                                    │
  └──────────────────────┬──────────────────────────────────────┘


  ┌─────────────────────────────────────────────────────────────┐
  │ ② HandlerMapping(处理器映射器)                             │
  │   根据 URL 找到对应的 Controller 和方法                       │
  │   RequestMappingHandlerMapping → 解析 @RequestMapping        │
  └──────────────────────┬──────────────────────────────────────┘
                         │ 返回 HandlerExecutionChain
                         │ (包含 Handler + 拦截器列表)

  ┌─────────────────────────────────────────────────────────────┐
  │ ③ HandlerAdapter(处理器适配器)                             │
  │   调用 Controller 方法,处理参数绑定、返回值                  │
  │   RequestMappingHandlerAdapter → 处理 @RequestMapping 方法    │
  └──────────────────────┬──────────────────────────────────────┘
                         │ 返回 ModelAndView

  ┌─────────────────────────────────────────────────────────────┐
  │ ④ ViewResolver(视图解析器)                                 │
  │   将逻辑视图名解析为实际视图(JSP / Thymeleaf 模板)           │
  │   前后端分离项目:直接返回 JSON,不经过 ViewResolver           │
  └──────────────────────┬──────────────────────────────────────┘


  ┌─────────────────────────────────────────────────────────────┐
  │ ⑤ View(视图渲染)                                          │
  │   渲染 HTML 返回给客户端                                     │
  │   前后端分离:HttpMessageConverter 将对象转为 JSON            │
  └─────────────────────────────────────────────────────────────┘

三、核心组件详解

3.1 HandlerMapping

java
// 根据 URL 匹配 Controller
// RequestMappingHandlerMapping 是默认实现,解析 @RequestMapping 注解

@RestController
@RequestMapping("/api/orders")
public class OrderController {

    @GetMapping("/{id}")          // 匹配 GET /api/orders/123
    public Order getOrder(@PathVariable Long id) { }

    @PostMapping                   // 匹配 POST /api/orders
    public Order createOrder(@RequestBody Order order) { }
}

3.2 HandlerAdapter

java
// 负责调用 Controller 方法,处理参数绑定、类型转换、数据校验
// RequestMappingHandlerAdapter 是默认实现

// 支持的参数类型(方法参数自动注入):
@GetMapping("/test")
public Result test(
    HttpServletRequest request,          // Servlet API
    HttpServletResponse response,
    @RequestParam("name") String name,   // 请求参数
    @PathVariable("id") Long id,         // 路径变量
    @RequestBody Order order,            // 请求体 JSON
    @RequestHeader("token") String token,// 请求头
    @CookieValue("sessionId") String sid,// Cookie
    Model model                          // 视图模型
) { }

3.3 HttpMessageConverter

java
// 前后端分离项目中,HTTP 消息转换器负责 JSON ↔ 对象转换

// ① 请求体 JSON → 对象(@RequestBody)
// {"name":"iPhone","price":6999} → Order 对象
// 使用:MappingJackson2HttpMessageConverter(Jackson)

// ② 对象 → 响应体 JSON(@ResponseBody / @RestController)
// Order 对象 → {"name":"iPhone","price":6999}
// 使用:MappingJackson2HttpMessageConverter(Jackson)

// 自定义配置
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 自定义 JSON 转换器
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(new ObjectMapper().setDateFormat(...));
        converters.add(converter);
    }
}

四、拦截器

java
// 拦截器:在请求到达 Controller 前后执行,类似 AOP 但专用于 Web 层
@Component
public class AuthInterceptor implements HandlerInterceptor {

    // ① Controller 执行前
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) {
        String token = request.getHeader("Authorization");
        if (token == null) {
            response.setStatus(401);
            return false;  // 返回 false 拦截请求,不继续往下走
        }
        return true;  // 返回 true 放行
    }

    // ② Controller 执行后,视图渲染前
    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) { }

    // ③ 视图渲染完成后
    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler, Exception ex) { }
}

// 注册拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private AuthInterceptor authInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor)
                .addPathPatterns("/api/**")      // 拦截的路径
                .excludePathPatterns("/api/login");  // 排除的路径
    }
}

五、拦截器 vs 过滤器

维度过滤器(Filter)拦截器(Interceptor)
归属Servlet 规范,Tomcat 管理Spring 框架,Spring 容器管理
执行时机进入 Servlet 之前进入 Controller 之前
粒度只能获取 request/response可以获取 Controller 方法信息
依赖注入不支持 @Autowired支持 @Autowired
生命周期随 Tomcat 启动随 Spring 容器启动
请求链路:

  请求 → Filter → DispatcherServlet → Interceptor → Controller

  Filter 在外层,Interceptor 在内层

六、统一异常处理

java
// @ControllerAdvice + @ExceptionHandler 全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {

    // 处理业务异常
    @ExceptionHandler(BusinessException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result handleBusinessException(BusinessException e) {
        return Result.error(e.getCode(), e.getMessage());
    }

    // 处理参数校验异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result handleValidation(MethodArgumentNotValidException e) {
        String msg = e.getBindingResult().getFieldErrors().stream()
                .map(FieldError::getDefaultMessage)
                .collect(Collectors.joining(", "));
        return Result.error("400", msg);
    }

    // 兜底处理
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result handleException(Exception e) {
        log.error("系统异常", e);
        return Result.error("500", "系统异常,请联系管理员");
    }
}

七、面试要点

Q1:Spring MVC 的请求处理流程是怎样的?

  请求 → DispatcherServlet → HandlerMapping 找到 Controller → HandlerAdapter 调用 Controller 方法 → 返回 ModelAndView → ViewResolver 解析视图 → 渲染返回。前后端分离项目中,HttpMessageConverter 将返回对象转为 JSON 直接写入响应。

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

  过滤器是 Servlet 规范,在 Tomcat 层面执行,进入 DispatcherServlet 之前;拦截器是 Spring 框架的,在 Controller 执行前后执行,可以获取 Controller 方法信息,支持依赖注入。

Q3:@RestController 和 @Controller 的区别?

  @RestController = @Controller + @ResponseBody。@Controller 返回视图名,@RestController 返回 JSON 数据(每个方法自动加 @ResponseBody)。