Spring MVC 基础

本专题导航#

主题
上一篇AOP 与事务
本篇Spring MVC
延伸Spring Boot Web、运维与测试

背景与动机#

IoC 管 Bean,AOP 管横切逻辑;到了 Web 层,还要解决:HTTP 请求怎么找到对应 Java 方法、参数怎么绑定、结果怎么变成 JSON 或页面。Spring MVC 就是 Spring 体系里的 Web 层框架,基于 Servlet,核心是 DispatcherServlet 统一调度

搞懂 MVC 流程,才能理解 Boot 里 @RestController 为什么能直接返回 JSON,以及 Filter、Interceptor、全局异常和 Controller 谁先谁后。

→ 前置:IoC 与依赖注入 · AOP 与事务

核心原理拆解#

1. Spring MVC 是什么#

基于 Servlet 规范的 Web 层框架(不是 Servlet 替代品),在 Servlet 容器(Tomcat、Jetty 等)之上工作:

职责说明
路由URL → Controller 方法
参数绑定Query、Path、Header、Body → 方法参数
调用链Controller → Service → DAO/Mapper
响应视图(JSP/Thymeleaf)或 JSON/XML(REST)

传统 Servlet 要手写 doGet/doPost、自己解析参数、自己写 JSON;MVC 用注解声明映射,由框架完成大部分样板代码。

2. 日常开发三层:Controller → Service → Mapper#

职责常见注解不该做的事
Controller接 HTTP、参数校验、组装返回@RestController@GetMapping复杂业务、直接写 SQL
Service业务逻辑、事务边界@Service@Transactional解析 HTTP 细节
Mapper / DAO持久化访问@Mapper + MyBatis XML业务规则、事务
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private final OrderService orderService;
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
@PostMapping
public OrderVO create(@RequestBody @Valid CreateOrderRequest req) {
return orderService.create(req);
}
}
@Service
public class OrderService {
@Transactional
public OrderVO create(CreateOrderRequest req) {
// 业务 + 调 Mapper
}
}

各层 Bean 由容器注入(推荐构造器注入)。
→ 注入 IoC 篇 · 事务 AOP 篇 · MyBatis Mapper 与 XML

分层原则:Controller 薄、Service 厚;事务标在 Service 的 public 方法上,不要标在 Controller。

3. 核心组件#

组件作用
DispatcherServlet前端控制器,所有请求入口,协调下面各组件
HandlerMapping根据 URL、HTTP 方法等找到处理器(Controller 方法)
HandlerAdapter适配不同处理器类型,真正调用 Controller 方法
HandlerInterceptor前置/后置/完成拦截(登录校验、日志,可选)
ViewResolver把逻辑视图名解析为具体视图(JSP 等)
HttpMessageConverter读写 HTTP 体:JSON ↔ Java 对象(Jackson)

REST 项目里,ViewResolver 用得少HttpMessageConverter(Jackson)负责把返回值序列化成 JSON。

4. 请求处理流程#

Client 发 HTTP 请求
→ Servlet 容器(Tomcat)
→ Filter 链(编码、安全等,可选)
→ DispatcherServlet
→ HandlerMapping:匹配 @GetMapping 等方法
→ HandlerInterceptor.preHandle(可选)
→ HandlerAdapter:调用 Controller 方法
→ Controller → Service → Mapper
→ 返回对象或 ModelAndView
→ HttpMessageConverter 写 JSON(@ResponseBody / @RestController)
→ HandlerInterceptor.postHandle / afterCompletion
→ 响应返回 Client

记忆口诀一进(DispatcherServlet)二找(Mapping)三调(Adapter)四转(Converter/View)

与 IoC 的关系:上述组件本身也是 Spring 容器里的 Bean;Boot 通过自动配置注册 DispatcherServlet 和默认 HandlerMapping

5. 常用注解#

类级别

注解作用
@Controller标记控制器;方法返回值默认作视图名
@RestController@Controller + @ResponseBody,REST 最常用
@RequestMapping类/方法路径前缀;可指定 method、consumes、produces

方法级别映射(Boot 里常用语义化子注解)

注解HTTP
@GetMappingGET
@PostMappingPOST
@PutMappingPUT
@DeleteMappingDELETE
@PatchMappingPATCH

参数绑定

注解绑定来源示例
@RequestParamQuery 参数?page=1@RequestParam int page
@PathVariable路径变量/users/{id}@PathVariable Long id
@RequestBody请求体 JSONPOST JSON → DTO 对象
@RequestHeader请求头Authorization
@CookieValueCookie
@ModelAttribute表单 / Model传统表单场景

校验与响应

注解作用
@Valid / @Validated触发 JSR-303 校验(配合 @NotNull 等)
@ResponseBody返回值直接写入 HTTP 体(@RestController 已含)
@ResponseStatus指定 HTTP 状态码
@GetMapping("/{id}")
public UserVO get(@PathVariable Long id,
@RequestParam(defaultValue = "false") boolean detail) {
return userService.find(id, detail);
}

6. REST API vs 传统 MVC 视图#

REST(前后端分离)传统 MVC(服务端渲染)
控制器@RestController@Controller
返回值DTO/VO → JSON视图名或 ModelAndView
视图无 / 前端 SPAJSP、Thymeleaf 等
核心组件HttpMessageConverterViewResolver

当前 Java 后端项目以 REST + JSON 为主;面试仍可能问 ModelAndView 和视图解析,知道即可。

7. Spring MVC 与 Spring Boot Web#

Spring Boot 的 spring-boot-starter-web 引入 spring-webmvc,并自动配置

  • 内嵌 Tomcat(或换 Jetty/Undertow)
  • DispatcherServlet 与默认 HandlerMapping
  • Jackson HttpMessageConverter
  • 静态资源、application.properties 里的 server.port

本质仍是 Spring MVC,只是省掉 XML 和 web.xml 里手动注册 Servlet 的步骤。Web 层进阶(全局异常、Actuator)→ Spring Boot Web、运维与测试

8. Spring、Spring Boot、Spring Cloud 关系#

框架定位
Spring Framework核心:IoC、AOP、MVC、事务
Spring Boot快速构建单个可运行应用(含 Web)
Spring Cloud微服务治理:注册发现、配置中心、网关、熔断等

Boot 可单独做单体或单个微服务;Cloud 建立在 Boot 之上,解决多服务协作。学 MVC 属于 Framework 层,Boot 只是启动与配置方式更简单。

常见陷阱与错误示例#

1. Controller 里写事务或复杂业务#

@Transactional 标在 Controller 上虽可能生效,但事务边界应放在 Service,便于复用和测试,也避免 Web 层逻辑渗进业务。

2. GET 请求带 @RequestBody#

HTTP 规范不禁止,但网关、缓存、部分客户端对 GET body 支持差;查询用 Query/Path,改改用 POST 或 RESTful 设计。

3. 路径变量名与参数名不一致未指定#

@PathVariable 默认按参数名匹配;不一致时需 @PathVariable("userId") Long id

4. 返回 Entity 直接暴露给前端#

应返回 VO/DTO,避免把数据库实体、懒加载字段、敏感字段直接序列化到 JSON。

5. 混淆 @Controller 与 @RestController#

@Controller 返回 "index" 会被当成视图名;REST 接口误用会导致 404 视图而不是 JSON。API 统一用 @RestController

6. 忽略 404/405 是 Mapping 问题#

404 常是 URL 或 HTTP 方法未匹配到 @XxxMapping;检查类上 @RequestMapping 前缀、是否多写了 /、是否被 context-path 影响。

面试高频问题#

更多速查见 Spring 面试题Spring Cloud 面试题 49 道

Spring MVC 执行流程?
请求进 DispatcherServletHandlerMapping 找处理器 → HandlerAdapter 调 Controller → 返回结果经 ViewResolverHttpMessageConverter 写回客户端。

DispatcherServlet 是什么?
前端控制器(Front Controller),Web 层总入口,解耦 Servlet 容器与 Spring 组件。

@RestController 和 @Controller 区别?
@RestController = @Controller + @ResponseBody,返回值序列化为 JSON 等;@Controller 默认走视图解析。

Spring MVC 和 Spring Boot 关系?
Boot Web 基于 Spring MVC,自动配置 DispatcherServlet、Jackson、内嵌容器;不是两套 Web 框架。

拦截器 Interceptor 和 Filter 区别?
Filter 属于 Servlet 规范,在 DispatcherServlet 之前;Interceptor 属于 Spring MVC,在 DispatcherServlet 之内,能拿到 Handler 信息。

一句话总结#

Spring MVC 的核心是 DispatcherServlet 调度 + HandlerMapping/Adapter 定位并调用 Controller;REST 项目靠 HttpMessageConverter 出 JSON,Boot Web 是其自动配置版,业务仍应 Controller 薄、Service 厚。

文章目录

文章目录