Spring MVC 核心架构与注解详解
一、Spring MVC 是什么 & 定位
Spring MVC 是 Spring Framework 框架的核心模块之一,是一款基于MVC 设计模式的轻量级 Java Web 开发框架,也是目前 Java 后端主流的 Web 开发技术。
价值:简化 Java Web 开发,将 Web 开发中的「请求接收、参数封装、业务处理、响应返回」等流程标准化、解耦化;
Spring MVC 是 Spring 框架的核心模块,基于 MVC 设计模式的轻量级 Java Web 开发框架。其核心架构与执行流程,包括前端控制器 DispatcherServlet、处理器映射器 HandlerMapping 等组件的作用。重点介绍了常用核心注解如@Controller、@RequestMapping、@ResponseBody 及其简化版,并提供了前后端分离与传统页面的入门示例。文章总结了 Spring MVC 的无缝集成、极致解耦等优势,适合 Java 后端开发者掌握主流 Web 开发技术。
Spring MVC 是 Spring Framework 框架的核心模块之一,是一款基于MVC 设计模式的轻量级 Java Web 开发框架,也是目前 Java 后端主流的 Web 开发技术。
价值:简化 Java Web 开发,将 Web 开发中的「请求接收、参数封装、业务处理、响应返回」等流程标准化、解耦化;
理念:遵循 约定优于配置 + 面向接口编程,兼顾灵活性和开发效率;
特性:原生兼容 Spring 生态(IoC、AOP)、轻量无侵入、组件化可插拔、支持 RESTful 风格、请求映射灵活、数据绑定强大。
Spring MVC 的本质是对 MVC 设计模式的完美落地实现,想要理解 Spring MVC,必须先理解 MVC。MVC 是所有 Web 开发的经典分层思想,和语言无关:
彻底解耦:三层职责单一,互不依赖。比如修改页面样式(View),完全不用改业务代码(Model);修改业务逻辑(Model),控制层(Controller)只需要调用对应方法即可,极大提升项目的可维护性和扩展性。
Spring MVC 是一个请求驱动的框架,所有请求都遵循「统一入口,统一出口」的标准化流程。
Spring MVC 的所有请求,都会经过一个 唯一的核心前端控制器 —— DispatcherServlet,它是整个 Spring MVC 的「总指挥」,所有请求的分发、调度都由它完成,开发者无需编写任何代码,只需在配置文件中配置即可。
DispatcherServlet(统一入口);DispatcherServlet 收到请求后,调用 处理器映射器 HandlerMapping;HandlerMapping 根据请求的「URL 地址 + 请求方式」,匹配对应的 处理器 Handler(本质就是我们写的 Controller 类),并返回处理器执行链(包含 Handler 和拦截器)给 DispatcherServlet;DispatcherServlet 调用 处理器适配器 HandlerAdapter;HandlerAdapter 适配并执行对应的 Handler(Controller),在 Controller 中:接收并封装请求参数;调用 Service 层的业务方法处理请求;处理完成后,返回 ModelAndView 对象(包含:业务数据 Model + 视图地址 View);HandlerAdapter 将执行结果(ModelAndView)返回给 DispatcherServlet;DispatcherServlet 调用 视图解析器 ViewResolver;ViewResolver 根据 ModelAndView 中的「视图地址」,解析出对应的 视图对象 View(比如 JSP/HTML);DispatcherServlet 将 Model 中的数据渲染到 View 中,生成最终的响应页面,通过 Web 服务器返回给客户端,请求结束。记忆:前端控制器是核心,所有组件都由它调度,开发者只需要写 Controller 和业务逻辑,其余组件 Spring MVC 都已内置实现。
上面流程中提到的组件,是 Spring MVC 的核心,全部由 Spring 容器管理,大部分组件开发者无需自定义,Spring 提供默认实现,这里讲清楚每个组件的核心作用:
RequestMappingHandlerMapping(Spring MVC 默认,支持 @RequestMapping 系列注解)。RequestMappingHandlerAdapter(Spring MVC 默认,适配 @RequestMapping 注解的 Controller)。index,视图解析器可以自动拼接前缀 /WEB-INF/views/ 和后缀 .jsp,最终得到完整路径 /WEB-INF/views/index.jsp。InternalResourceViewResolver(默认,支持 JSP 解析)。Spring MVC 基于注解驱动开发,完全摒弃了早期的 XML 配置方式,所有核心功能都通过注解实现,以下是开发中常用到的核心注解,按使用频率排序:
@ResponseBody 注解,可让 Controller 直接返回 JSON 数据(前后端分离项目必用)。value/path:指定请求 URL(必填);method:指定请求方式(GET/POST/PUT/DELETE),如 method = RequestMethod.GET;params:限制请求必须携带指定参数才会匹配;@RestController
@RequestMapping("/user")
// 类上:所有方法的 URL 前缀都是 /user
public class UserController {
// 方法上:完整请求 URL = /user/query,仅处理 GET 请求
@RequestMapping(value = "/query", method = RequestMethod.GET)
public String query() {
return "查询用户";
}
}
是 @RequestMapping 的专用简化版,语义更清晰,开发中常用这些代替 @RequestMapping:
@GetMapping("url") → 等价于 @RequestMapping(value="url",method=RequestMethod.GET) → 处理 GET 请求(查询);@PostMapping("url") → 等价于 @RequestMapping(value="url",method=RequestMethod.POST) → 处理 POST 请求(新增);@PutMapping("url") → 处理 PUT 请求(修改);@DeleteMapping("url") → 处理 DELETE 请求(删除);@RestController = @Controller + @ResponseBody → 前后端分离项目的标配,标记的 Controller 所有方法都返回 JSON,不会跳转视图。"index" 会跳转 index.jsp 页面);加了该注解后,返回值就是纯数据,不再跳转页面;搭配 @Controller 使用,适合「部分方法返回 JSON、部分方法跳转页面」的混合场景。用于在 Controller 方法中接收前端传递的参数,开发中高频使用:
@RequestParam("参数名"):接收 URL 拼接参数(GET)或表单提交参数(POST),如 @RequestParam("name") String username;
value/name:必填,指定前端传递的参数名,必须和前端一致;required:可选,默认 true,表示该参数必须传递,不传则报错;设为 false 则参数可选;defaultValue:可选,给参数设置默认值,当参数未传递 / 传递空值时生效。// 请求 URL:http://localhost:8080/user/query?name=张三&age=20
@GetMapping("/query")
// 接收 name 和 age 参数,age 可选,默认值 18
public String query(@RequestParam("name") String username, @RequestParam(value = "age", required = false, defaultValue = "18") Integer age) {
return "姓名:" + username + ",年龄:" + age;
}
若:后端参数名 = 前端参数名,可以省略注解,直接写参数即可,底层自动映射:
// 等价于上面的写法,name 和前端参数名一致,可省略 @RequestParam
public String query(String name, Integer age) {
...
}
@PathVariable("占位符"):接收 RESTful 风格的 URL 路径参数,如 @GetMapping("/user/{id}") 中,用 @PathVariable("id") Integer id 接收;
{参数名} 定义占位符;value 值必须和占位符的参数名一致;// 请求 URL:http://localhost:8080/user/1001/info
@GetMapping("/{userId}/info")
// {userId} 是路径占位符
public String getUserInfo(@PathVariable("userId") String id) {
return "用户 ID:" + id;
}
@RequestBody:接收前端传递的 JSON 格式请求体(POST/PUT 必用),直接封装到实体类中,如 @RequestBody User user;
Content-Type = application/json;// 前端 POST 请求,请求体是 JSON:{"name":"张三","age":20,"phone":"13800138000"}
@PostMapping("/add")
// 自动将 JSON 请求体封装为 User 实体类对象
public String addUser(@RequestBody User user) {
return "新增用户:" + user.getName();
}
作用:接收前端在 HTTP 请求头 中传递的参数,比如 token、Content-Type、User-Agent 等。
// 接收请求头中的 token 参数,用于接口鉴权
@GetMapping("/auth")
public String auth(@RequestHeader("token") String token) {
return "请求头中的令牌:" + token;
}
作用:接收前端浏览器在请求中携带的 Cookie 数据,比如登录后的 Cookie 令牌。
@GetMapping("/cookie")
public String getCookie(@CookieValue("JSESSIONID") String sessionId) {
return "Cookie 中的会话 ID:" + sessionId;
}
@ModelAttribute@RequestParam,简化表单参数的封装,比如提交用户信息时,直接封装为 User 对象。@CrossOrigin@RestController
@RequestMapping("/user")
@CrossOrigin
// 所有方法允许跨域请求
public class UserController {
...
}
下面给出基于注解的最简 Spring MVC 入门案例,包含核心配置 + 核心代码,能直观看到 Spring MVC 的开发方式,分「传统前后端一体」和「前后端分离(主流)」两种最常用场景。
spring-webmvc// 组合注解:@Controller + @ResponseBody,所有方法返回 JSON
@RestController
// 类级请求前缀:所有方法的 URL 都以 /user 开头
@RequestMapping("/user")
public class UserController {
// 处理 GET 请求,完整 URL:http://localhost:8080/user/info/1
@GetMapping("/info/{id}")
public User getUserInfo(@PathVariable("id") Integer id) {
// 模拟业务逻辑:根据 ID 查询用户
User user = new User();
user.setId(id);
user.setName("张三");
user.setAge(20);
// 直接返回实体类,Spring MVC 自动转为 JSON 响应给前端
return user;
}
// 处理 POST 请求,接收前端 JSON 参数,完整 URL:http://localhost:8080/user/add
@PostMapping("/add")
public Result addUser(@RequestBody User user) {
// 模拟新增用户业务
System.out.println("新增用户:" + user);
// 返回统一响应结果
return Result.success("新增用户成功");
}
}
// 实体类:User
class User {
private Integer id;
private String name;
private Integer age;
// getter/setter 省略
}
// 统一响应结果类:Result
class Result {
private Integer code;
private String msg;
private Object data;
// 静态工具方法:success/error 省略
}
// 只加 @Controller,方法返回视图名称,不是 JSON
@Controller
@RequestMapping("/page")
public class PageController {
// 处理 GET 请求,URL:http://localhost:8080/page/index
@GetMapping("/index")
public ModelAndView index() {
// 创建 ModelAndView 对象,封装数据 + 视图地址
ModelAndView mv = new ModelAndView();
// 1. 往 Model 中存数据(前端页面可以获取)
mv.addObject("msg", "欢迎使用 Spring MVC");
// 2. 设置视图名称,视图解析器会拼接前缀 + 后缀
mv.setViewName("index");
// 最终视图路径:/WEB-INF/views/index.jsp
return mv;
}
}
@Controller/@RestController、@RequestMapping及简化版@GetMapping/@PostMapping、@ResponseBody、@RequestParam/@PathVariable/@RequestBody;@RestController返回 JSON,是目前企业开发的标配;
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online