
一、基本定义Spring MVC全称 Spring Web MVC是 Spring 框架原生提供的Web 层应用开发框架基于经典的 MVC 设计模式实现是 Java 企业级开发中最主流的 Web 开发方案之一主要用于构建传统 Web 页面应用与 RESTful 接口服务。它建立在 Servlet API 之上对原生 Servlet 开发的繁琐流程做了深度封装让开发者只需关注业务逻辑编写无需手动处理参数解析、响应封装、路径映射等重复工作。二、MVC 设计模式与 Spring MVC 的对应MVC 是一种软件架构设计思想将 Web 应用按职责拆分为三层实现关注点分离Model模型层负责数据封装与核心业务逻辑对应 Java 实体类、Service 业务层、DAO 数据层View视图层负责数据展示与页面渲染对应 JSP、Thymeleaf 模板页、前端页面Controller控制层负责接收请求、调用模型、返回视图 / 数据对应 Spring MVC 中的 Controller 组件在当前前后端分离的主流场景下View 层由前端独立实现Spring MVC 通常只负责提供数据接口返回 JSON此时 Controller 直接返回业务数据对象由框架自动序列化为 JSON 响应。三、核心工作流程请求全链路Spring MVC 的核心中枢是DispatcherServlet前端控制器所有 HTTP 请求都会先经过它再由它统一调度各个组件完成处理。完整请求处理流程如下用户发起 HTTP 请求请求被DispatcherServlet统一接收DispatcherServlet调用HandlerMapping根据请求 URL 匹配对应的 Controller 方法并组装拦截器链DispatcherServlet调用HandlerAdapter由适配器适配并执行目标 Controller 方法Controller 执行业务逻辑返回处理结果视图名、ModelAndView、JSON 对象等HandlerAdapter将执行结果返回给DispatcherServlet若返回视图名DispatcherServlet调用ViewResolver视图解析器将逻辑视图名解析为具体的 View 对象DispatcherServlet调用 View 对象进行视图渲染将 Model 数据填充到视图中最终DispatcherServlet将渲染结果或 JSON 数据作为 HTTP 响应返回给用户四、核心组件说明表格组件核心作用DispatcherServlet前端控制器整个框架的调度中枢统一接收请求并分发降低各组件耦合HandlerMapping处理器映射器建立请求 URL 与 Controller 方法的映射关系同时组装拦截器链HandlerAdapter处理器适配器采用适配器模式统一调用不同类型的 Controller屏蔽调用方式的差异Handler / Controller业务处理器由开发者编写负责接收参数、调用业务层、返回处理结果ViewResolver视图解析器将逻辑视图名如login解析为具体的视图对象如 JSP、Thymeleaf 页面View视图负责数据渲染将 Model 数据填充后生成最终的 HTML、JSON、Excel 等响应内容HandlerInterceptor拦截器在请求处理的三个节点Controller 执行前、执行后、请求结束后插入自定义逻辑五、核心优势与特性Spring 生态无缝集成天然支持 Spring 的依赖注入DI、AOP、事务管理等能力Spring 容器中的 Bean 可直接在 Controller 中注入使用。注解驱动开发通过Controller、RequestMapping、RequestParam、ResponseBody等注解极大简化配置替代了传统 Servlet 繁琐的 web.xml 配置。强大的参数绑定与转换自动将请求参数查询参数、表单、JSON 请求体封装为 Java 对象支持类型自动转换、数据校验、日期格式化等能力。高度可扩展支持自定义拦截器、参数解析器、消息转换器、视图解析器、异常处理器可灵活适配各类业务需求。RESTful 友好原生支持 REST 风格接口开发通过RestController、路径变量、HTTP 方法语义化GET/POST/PUT/DELETE快速构建标准化接口。多视图兼容支持 JSP、Thymeleaf、Freemarker、Excel、PDF 等多种视图输出形式满足不同业务场景。六、补充与 Servlet 过滤器的执行顺序上一问提到的拦截器是 Spring MVC 的内部组件而过滤器Filter是 Servlet 官方规范的组件二者执行顺序为Servlet 过滤器 → DispatcherServlet → Spring MVC 拦截器 → Controller过滤器作用于请求进入 Servlet 容器的阶段拦截器作用于 Spring MVC 内部的请求生命周期。在 Spring Boot 环境中Spring MVC 相关组件会被自动配置开发者只需引入spring-boot-starter-web依赖即可直接使用无需手动配置 DispatcherServlet 和基础视图解析器。Spring MVC 常用注解详解附完整示例以下按使用频率从高到低分类讲解全部基于 Spring Boot 环境覆盖日常开发 95% 以上的场景。一、控制器类注解类级别1. Controller作用标记一个类为 Spring MVC 控制器负责接收并处理 HTTP 请求传统页面开发中用于返回逻辑视图名。位置类上方特点默认方法返回值会被当做视图名走视图解析器渲染页面若要返回 JSON 数据需要在方法上额外加ResponseBody。Controller RequestMapping(/page) public class PageController { // 返回 login 视图名视图解析器会匹配到 login.html / login.jsp GetMapping(/login) public String loginPage() { return login; } }2. RestController作用复合注解 ControllerResponseBody是前后端分离项目的首选。位置类上方特点类中所有方法默认直接返回数据JSON/XML不会走视图解析器无需每个方法单独加ResponseBody。RestController RequestMapping(/api/user) public class UserController { // 直接返回 JSON 格式的字符串/对象 GetMapping(/hello) public String hello() { return hello spring mvc; } }二、请求映射注解类 方法级别用于建立「请求 URL 请求方式」与「处理方法」的映射关系。1. RequestMapping作用通用请求映射注解可标注在类和方法上类上定义父路径方法上定义子路径。核心属性value / path请求路径支持数组配置多个路径method指定请求方式RequestMethod.GET/POST/PUT/DELETE等params限定请求必须包含 / 不包含指定参数consumes限定请求体的媒体类型如application/jsonproduces限定响应的媒体类型RestController RequestMapping(/api/user) // 类级别的父路径 public class UserController { // 匹配 GET /api/user/list?typeadmin RequestMapping(value /list, method RequestMethod.GET, params typeadmin) public String list() { return 管理员用户列表; } }2. REST 风格派生注解等价于指定了method的RequestMapping是目前接口开发的主流写法注解对应请求方式典型用途GetMappingGET查询数据PostMappingPOST新增数据PutMappingPUT修改全量数据DeleteMappingDELETE删除数据PatchMappingPATCH修改部分数据RestController RequestMapping(/api/user) public class UserController { GetMapping(/{id}) // GET 查询单个用户 public String getById(PathVariable Long id) { return 查询用户: id; } PostMapping // POST 新增用户 public String addUser() { return 新增用户; } PutMapping // PUT 修改用户 public String updateUser() { return 修改用户; } DeleteMapping(/{id}) // DELETE 删除用户 public String deleteUser(PathVariable Long id) { return 删除用户: id; } }三、请求参数绑定注解方法参数级别这是开发中最核心的一类注解用于把 HTTP 请求中的数据自动注入到方法参数中。1. RequestParam作用获取URL 查询参数、表单参数application/x-www-form-urlencoded核心属性name / value对应请求中的参数名required是否必填默认truedefaultValue参数未传时的默认值GetMapping(/page) // 请求示例GET /api/user/page?pageNum1pageSize20 public String pageList( RequestParam(pageNum) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize // 不传默认10 ) { return 第 pageNum 页每页 pageSize 条; }2. PathVariable作用获取 URL 路径中的变量是RESTful 风格接口的核心注解。场景把参数放在路径中如/user/100中的100GetMapping(/{id}/{name}) // 请求示例GET /api/user/100/zhangsan public String getInfo( PathVariable Long id, PathVariable String name ) { return id: id , name: name; }3. RequestBody作用接收JSON 格式的请求体自动将 JSON 反序列化为 Java 对象。场景POST/PUT 请求提交复杂对象数据前后端分离最常用。注意一个方法中最多只能有一个RequestBodyGET 请求没有请求体不能使用。先定义实体类public class User { private Long id; private String username; private Integer age; // getter、setter、无参构造省略 }使用示例PostMapping(/add) // 请求体{id:1,username:张三,age:20} public String addUser(RequestBody User user) { return 新增用户 user.getUsername(); }4. RequestHeader作用获取指定请求头的值GetMapping(/header) public String getHeader(RequestHeader(token) String token) { return 请求头中的token token; }5. CookieValue作用获取 Cookie 中的指定值GetMapping(/cookie) public String getCookie(CookieValue(JSESSIONID) String sessionId) { return SessionID sessionId; }四、响应与状态注解1. ResponseBody作用将方法返回值直接作为 HTTP 响应体输出自动通过消息转换器序列化为 JSON。位置方法上 / 类上说明RestController已经默认包含此注解仅在Controller类中需要返回 JSON 时单独使用。Controller public class TestController { ResponseBody GetMapping(/json) public User jsonTest() { return new User(1L, 张三, 20); // 直接返回 JSON 对象 } }2. ResponseStatus作用自定义响应的 HTTP 状态码和提示信息位置方法上 / 异常类上PostMapping(/create) ResponseStatus(code HttpStatus.CREATED, reason 创建成功) public void create() { // 业务逻辑响应状态码为 201 }五、全局增强与异常处理注解1. ControllerAdvice RestControllerAdvice作用控制器全局增强组件用于实现全局异常处理、全局数据绑定、全局参数预处理。RestControllerAdviceControllerAdviceResponseBody统一返回 JSON 格式的异常结果。2. ExceptionHandler作用捕获指定类型的异常进行统一处理可写在 Controller 内做局部异常处理也可配合RestControllerAdvice做全局异常处理。全局异常处理完整示例RestControllerAdvice public class GlobalExceptionHandler { // 捕获参数非法异常 ExceptionHandler(IllegalArgumentException.class) ResponseStatus(HttpStatus.BAD_REQUEST) public String handleIllegalArg(IllegalArgumentException e) { return 参数错误 e.getMessage(); } // 捕获所有未处理的系统异常 ExceptionHandler(Exception.class) ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public String handleException(Exception e) { return 系统异常请联系管理员; } }六、综合实战完整示例1. 实体类 User.javapublic class User { private Long id; private String username; private Integer age; public User() {} public User(Long id, String username, Integer age) { this.id id; this.username username; this.age age; } // getter、setter 省略 }2. 用户控制器 UserController.javaimport org.springframework.web.bind.annotation.*; RestController RequestMapping(/api/users) public class UserController { // 1. 路径变量 GET 查询单个用户 GetMapping(/{id}) public User getUserById(PathVariable Long id) { return new User(id, 用户 id, 20); } // 2. 查询参数 分页列表 GetMapping(/list) public String listUsers( RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize ) { return 分页查询第 pageNum 页每页 pageSize 条; } // 3. JSON请求体 新增用户 PostMapping public String addUser(RequestBody User user) { return 新增成功 user.getUsername(); } // 4. 路径变量 JSON请求体 修改用户 PutMapping(/{id}) public String updateUser(PathVariable Long id, RequestBody User user) { return 修改ID为 id 的用户 user.getUsername(); } // 5. 路径变量 删除用户 DeleteMapping(/{id}) public String deleteUser(PathVariable Long id) { return 删除用户ID id; } }3. 全局异常处理 GlobalExceptionHandler.javaimport org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; RestControllerAdvice public class GlobalExceptionHandler { ExceptionHandler(IllegalArgumentException.class) ResponseStatus(HttpStatus.BAD_REQUEST) public String paramError(IllegalArgumentException e) { return 请求参数非法 e.getMessage(); } ExceptionHandler(Exception.class) ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public String systemError() { return 服务器内部错误请稍后重试; } }七、常见易错点GET 请求不能用RequestBodyGET 协议没有请求体传参只能用RequestParam或PathVariable。一个方法只能有一个RequestBody请求体只有一个无法拆分注入多个对象。RestController不会走视图解析器如果需要返回页面必须用Controller。PathVariable可选参数若要让路径变量可选需配置required false同时路径要支持空匹配。