跳到主要内容
Spring Web MVC 核心概念与实战指南 | 极客日志
Java 大前端 java
Spring Web MVC 核心概念与实战指南 Spring Web MVC 基于 Servlet API 构建,是 Spring 框架的核心 Web 模块。本文详解 MVC 设计模式、项目搭建、核心注解(如 @RequestMapping、@RequestBody)及请求处理流程。涵盖参数接收、JSON 交互、文件上传、Cookie/Session 管理及静态资源返回。通过加法计算器、登录系统等实战案例,结合 Postman 测试与 Lombok 优化,提供从理论到企业级开发规范的完整指南,帮助开发者快速掌握 Spring MVC 核心能力。
Spring Web MVC 核心概念与实战指南
1. Spring Web MVC 核心概念
1.1 什么是 Spring Web MVC
Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从一开始就包含在 Spring 框架中。其正式名称来源于源模块名称(spring-webmvc),通常简称为 Spring MVC。
Servlet 是 Java Web 开发的规范,定义了动态页面开发的技术标准,而 Tomcat、Weblogic 等 Servlet 容器则是该规范的具体实现。Spring MVC 基于 Servlet 规范实现,为 Web 应用开发提供了完整的解决方案。
1.2 MVC 设计模式深度解析
MVC 是 Model View Controller 的缩写,将软件系统分为模型、视图和控制器三个基本部分,实现业务逻辑与界面展示的解耦。
1.2.1 MVC 三大组件职责
Model(模型) :应用程序的主体部分,负责处理数据逻辑和业务逻辑,包含数据的存储、处理和运算。
View(视图) :专门用于与用户交互的界面,负责数据展示和接收用户操作,如 HTML 页面、移动端界面等。
Controller(控制器) :作为视图与模型之间的桥梁,接收用户请求,选择对应的模型进行处理,并将处理结果通过视图返回给用户。
类比理解 :以饭店就餐场景为例。
服务员(View):接待顾客、记录点餐信息、上菜。
前厅(Controller):接收订单,分配给后厨处理,协调流程。
后厨(Model):根据订单需求制作菜品,处理核心业务逻辑。
1.3 Spring MVC 与 Spring Boot 的关系
Spring Boot 并非替代 Spring MVC,而是实现 Spring MVC 的一种便捷方式。Spring Boot 如同一个功能完备的厨房,而 Spring MVC 则是厨房中实现烹饪功能的燃气灶。厨房可通过配置不同工具实现多种功能,而烹饪的核心实现依赖于燃气灶。
特性 Spring MVC Spring Boot 本质 Web 框架,实现 MVC 模式 快速开发脚手架 核心作用 处理 Web 请求与响应 简化 Spring 应用配置与部署 依赖关系 可独立使用 可集成 Spring MVC 实现 Web 功能
2. Spring MVC 项目搭建与环境配置
2.1 项目创建步骤
Spring MVC 项目通常通过 Spring Boot 方式创建:
新建 Spring Boot 项目,选择 Spring Boot 版本(推荐 3.2.0 及以上)。
在依赖选择界面勾选 Spring Web 模块(即 Spring MVC 核心依赖)。
配置项目基本信息(Group、Artifact、Package 等),完成项目创建。
2.2 核心依赖说明
创建后的项目 pom.xml 文件中,Spring Web 依赖自动引入:
<dependency >
<groupId > org.springframework.boot
spring-boot-starter-web
</groupId >
<artifactId >
</artifactId >
</dependency >
该依赖包含 Spring MVC 核心组件、Servlet API、Tomcat 嵌入式容器等关键资源,无需额外配置即可实现 Web 功能开发。
3. Spring MVC 核心注解与应用
3.1 路由映射注解 @RequestMapping @RequestMapping 是最基础的路由映射注解,用于将 URL 请求与 Java 方法关联,支持修饰类和方法。
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/sayHi")
public String sayHi () {
return "hello, Spring MVC" ;
}
}
类级注解 :设置请求路径的初始前缀,所有方法路由需拼接该前缀。
方法级注解 :设置具体的请求路径,可支持多层路径(如 /say/hi)。
路径规则 :URL 路径最前是否加 / 不影响访问,Spring 会自动补全。路径 + 请求方式是唯一的,可以相同的路径名字但是不同类型的请求。
3.2 请求参数接收注解
3.2.1 @RequestParam 参数重命名 用于解决前后端参数名称不一致问题,同时可设置参数是否必传:
@RequestMapping("/r6")
public String r6 (@RequestParam(value = "sa", required = false) String resouce) {
return "接收到 resouce = " + resouce;
}
value 属性 :指定前端传递的参数名称。
required 属性 :默认值为 true,设置为 false 时参数非必传。
3.2.2 @PathVariable 获取路径参数 用于从 URL 路径中直接提取参数,适用于 RESTful 风格接口:
@RequestMapping("/r11/{articleId}/{type}")
public String r11 (@PathVariable("articleId") Integer id, @PathVariable String type) {
return "接收到的参数 articleId = " + id + ", type = " + type;
}
访问路径示例:http://127.0.0.1:8080/param/m8/5/zhangsan,其中 5 和 zhangsan 分别映射到 id 和 userName 参数。
3.3 响应处理注解
@ResponseBody :标识方法返回数据而非视图,可修饰类或方法。
@RestController :组合注解,等价于 @Controller + @ResponseBody,类中所有方法默认返回数据。
@Controller
public class IndexController {
@RequestMapping("/index")
public String index () {
return "/index.html" ;
}
}
@RestController
public class DataController {
@RequestMapping("/data")
public String getData () {
return "这是返回的数据内容" ;
}
}
4. 请求处理全场景实战
4.1 基础参数传递
4.1.1 单个参数接收 直接通过方法参数接收前端传递的参数,参数名称 需与请求参数 一致:
@RequestMapping("/r1")
public String r1 (String name) {
return "接收到参数 name = " + name;
}
访问示例:http://127.0.0.1:8080/request/r1?name=zhangsan
4.1.2 多个参数接收 支持多个参数同时接收 ,参数顺序不影响绑定结果(请求的参数名称保持一致即可) :
@RequestMapping("/r4")
public String r4 (String name, String password, Integer age) {
return "接收到参数 name = " + name + ", password = " + password + ", age = " + age;
}
访问示例:http://127.0.0.1:8080/request/r4?age=20&name=zhangsan&password=123456
4.2 复杂参数处理
4.2.1 对象参数接收 当参数较多时,可封装为实体类接收,Spring 会自动按属性名绑定 :
public class Person {
private String name;
private String password;
private int age;
}
@RequestMapping("/r5")
public String r5 (Person person) {
return "接收到参数 person = " + person;
}
4.2.2 参数重命名 通过 @RequestParam() 注解使得参数进行重命名与前端发的请求保持一致。且加了这个注解,此参数就为必传参数,如果不传则会报出 400 状态,除非将 @RequestParam("sa") 修改为 @RequestParam(value = "sa", required = false)。
@RequestMapping("/r6")
public String r6 (@RequestParam("sa") String resouce) {
return "接收到 resouce = " + resouce;
}
4.2.3 数组与集合参数 @RequestMapping("/r7")
public String r7 (String[] names) {
return "接收到参数 names = " + Arrays.toString(names);
}
访问示例:http://127.0.0.1:8080/request/r7?names=zhangsan&names=lisi&names=wangwu
也可以使用 http://127.0.0.1:8080/request/r7?names=zhangsan,lisi,wangwu
集合参数接收(需配合 @RequestParam):
@RequestMapping("/r8")
public String r8 (@RequestParam List<String> names) {
return "接收到的参数 names = " + names;
}
注意:未使用 @RequestParam 绑定会报出 500 错误,正确绑定则正常。
4.3 传递 JSON 数据
4.3.1 JSON 概念与优势 JSON(JavaScript Object Notation)是一种轻量级的文本数据交互格式,基于 ECMAScript 规范的子集。核心优势包括简单易用、跨平台兼容、轻量高效、结构灵活及安全性高。
4.3.2 JSON 语法与核心结构
基础语法规则 :数据以键值对形式存储,Key 必须用双引号包裹;字符串类型值需用双引号包裹;注释不支持。
两种核心结构 :对象结构 {} 存储无序键值对;数组结构 [] 存储有序值列表。
4.3.3 JSON 与 Java 对象互转 Spring MVC 框架默认集成 jackson-databind 工具包,无需额外引入,可直接实现 JSON 字符串与 Java 对象的序列化与反序列化。
package cn.overthinker.springboot;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JSONTests {
private static ObjectMapper objectMapper = new ObjectMapper ();
public static void main (String[] args) throws JsonProcessingException {
Person person = new Person ();
person.setName("zhangsan" );
person.setAge(18 );
person.setPassword("123456" );
String s = objectMapper.writeValueAsString(person);
System.out.println(s);
String json = "{\"name\":\"zhangsan\",\"age\":18,\"password\":\"123456\"}" ;
Person person1 = objectMapper.readValue(json, Person.class);
System.out.println(person1);
}
}
若转换集合(如 List),需用 TypeReference 指定泛型类型。
4.3.4 Spring MVC 接收 JSON 请求 后端需通过 @RequestBody 注解绑定请求正文,触发 Spring 的 JSON 解析逻辑。
@RequestMapping("/r9")
public String r9 (@RequestBody Person person) {
return "接收到的参数 person = " + person;
}
前端请求时需设置 Header:Content-Type: application/json。
4.4 文件上传功能实现 使用 @RequestPart 注解实现文件上传功能:
@RequestMapping("/r12")
public String r12 (MultipartFile file) throws IOException {
System.out.println("表单文件参数名:" + file.getName());
System.out.println("文件原始名称:" + file.getOriginalFilename());
System.out.println("文件 MIME 类型:" + file.getContentType());
File destFile = new File ("D:/temp/" + file.getOriginalFilename());
file.transferTo(destFile);
return "接受到文件,已保存至 D:/temp 目录" ;
}
4.5 Cookie 与 Session 会话管理 Cookie 通常存储在客户端,Session 存储在服务器端。
4.5.1 Cookie 操作 方式一:通过 HttpServletRequest 和 HttpServletResponse 获取:
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@RequestMapping("/getCookie")
public String getCookie (HttpServletRequest request, HttpServletResponse response) {
Cookie[] cookies = request.getCookies();
if (cookies != null ) {
for (Cookie cookie : cookies) {
System.out.println(cookie.getName() + ":" + cookie.getValue());
}
}
return "获取 Cookie 成功" ;
}
@RequestMapping("/getCookie2")
public String getCookie2 (@CookieValue("class") String className) {
return "获取 Cookie 成功 className:" + className;
}
4.5.2 Session 操作 @RequestMapping("/setSession")
public String setSession (HttpSession session) {
session.setAttribute("name" , "zhangsan" );
session.setAttribute("age" , 20 );
return "设置 Session 成功" ;
}
@RequestMapping("/getSession")
public String getSession (HttpSession session) {
String name = (String) session.getAttribute("name" );
Integer age = (Integer) session.getAttribute("age" );
return "从 session 中获取数据,name:" + name + ", age:" + age;
}
方案二:通过 @SessionAttribute 注解
@RequestMapping("/getSession3")
public String getSession3 (@SessionAttribute("name") String name) {
return "从 session 中获取数据,name:" + name;
}
注意 :Session 是基于服务器端的会话标识(SessionID)来区分用户的。如果交换 SessionID,保存的信息也会随之交换。
方案一:通过 HttpServletRequest
@RequestMapping("/getHeader")
public String getHeader (HttpServletRequest request) {
String userAgent = request.getHeader("User-Agent" );
return "从 Header 获取数据,userAgent" + userAgent;
}
@RequestMapping("/getHeader2")
public String getHeader2 (@RequestHeader("User-Agent") String userAgent) {
return "从 Header 获取数据,userAgent" + userAgent;
}
5. 响应处理高级应用
5.1 静态页面返回 返回静态页面需使用 @Controller 注解(而非 @RestController):
@Controller
public class IndexController {
@RequestMapping("/index")
public String index () {
return "/index.html" ;
}
}
静态页面需放置在 resources/static 目录下,访问路径为:http://127.0.0.1:8080/index
5.2 JSON 数据响应 Spring MVC 可自动将对象转换为 JSON 格式响应:
@ResponseBody
@RequestMapping("/returnJson")
public HashMap<String, String> returnJson () {
HashMap<String, String> map = new HashMap <>();
map.put("Java" , "Java Value" );
map.put("MySQL" , "MySQL Value" );
map.put("Redis" , "Redis Value" );
return map;
}
@RequestMapping("/setStatus")
@ResponseBody
public String setStatus (HttpServletResponse response) {
response.setStatus(401 );
return "设置状态码成功" ;
}
@RequestMapping("/setHeader")
@ResponseBody
public String setHeader (HttpServletResponse response) {
response.setHeader("MyHeader" , "MyHeaderValue" );
return "设置 Header 成功" ;
}
6. 综合项目实战
6.1 加法计算器
请求路径 :/calc/sum
请求方式 :GET/POST
参数 :num1(Integer,必填)、num2(Integer,必填)
响应 :计算结果 HTML 页面
@RestController
@RequestMapping("/calc")
public class CalcController {
@RequestMapping("/sum")
public String sum (Integer num1, Integer num2) {
Integer sum = num1 + num2;
return "<h1>计算机计算结果:" + sum + "</h1>" ;
}
}
6.2 用户登录系统
核心功能 :账号密码校验、登录状态保持(Session)、首页显示当前登录用户。
@RestController
@RequestMapping("/user")
public class LoginController {
@RequestMapping("/login")
public boolean login (String userName, String password, HttpSession session) {
if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
return false ;
}
if ("zhangsan" .equals(userName) && "123456" .equals(password)) {
session.setAttribute("userName" , userName);
return true ;
}
return false ;
}
@RequestMapping("/getLoginUser")
public String getLoginUser (HttpSession session) {
String userName = (String) session.getAttribute("userName" );
if (StringUtils.hasLength(userName)) {
return userName;
}
return "" ;
}
}
6.3 图书管理系统 @RestController
@RequestMapping("/book")
public class BookController {
@RequestMapping("/getList")
public List<BookInfo> getList () {
BookService bookService = new BookService ();
return bookService.getBookList();
}
}
7. 开发工具与效率提升
7.1 Postman 接口测试 Postman 是后端开发常用的接口测试工具,支持多种请求方式、参数类型,无需编写前端代码即可完成接口测试。
下载安装 Postman。
创建请求:选择请求方式(GET/POST)、输入 URL。
配置参数:根据接口类型选择参数格式(Query Params、form-data、JSON 等)。
发送请求:点击 Send 按钮,查看响应结果。
7.2 Lombok 简化开发 Lombok 是 Java 开发工具库,通过注解自动生成 getter/setter、toString 等冗余代码。
<dependency >
<groupId > org.projectlombok</groupId >
<artifactId > lombok</artifactId >
<optional > true</optional >
</dependency >
@Data:生成 getter/setter、toString、equals 等方法。
@Getter / @Setter:仅生成对应方法。
@NoArgsConstructor / @AllArgsConstructor:生成构造方法。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private int id;
private String name;
private String password;
}
8. 企业开发规范
命名规范 :类名大驼峰,方法名小驼峰,包名全小写。
代码格式 :缩进 4 个空格,关键业务逻辑添加注释。
注解使用 :优先使用组合注解(如 @RestController)。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online