← 返回上一页

第2章: 数据绑定

前端传过来的数据,SpringMVC 怎么自动"接住"?

学习进度 0/5

1. 什么是数据绑定?一个比喻就懂

📮 想象你是快递站的分拣员

前端发来的请求就像一个快递包裹,上面贴着标签:name=张三age=20email=test@qq.com

你需要把这些标签上的信息填到一张登记表(Java 对象)上。如果一个一个手动填,很累!

数据绑定就是 SpringMVC 帮你自动填表!前端传什么参数名,SpringMVC 就自动赋值到对应的变量或对象字段上。

简单说:数据绑定 = 把 HTTP 请求中的参数,自动变成 Java 变量/对象

前端怎么传 后端怎么接
URL 查询参数 ?name=张三 @RequestParam String name
URL 路径 /user/123 @PathVariable Long id
表单提交 name=张三&age=20 直接用 User user(POJO 绑定)
JSON 请求体 {"name":"张三"} @RequestBody User user
文件上传 MultipartFile file
💡 本章目标:

学完本章,你能在项目中自如地接收前端传来的任何类型的数据——字符串、数字、对象、JSON、文件。

2. POJO 对象绑定(最常用!)

前端传了一堆参数,你不想一个一个 @RequestParam 接,怎么办?
直接定义一个 Java 对象,SpringMVC 自动帮你填好!

1

先创建实体类

// 📄 User.java — 用户实体类(POJO 绑定的核心) package com.example.springmvcdemo.entity; public class User { private String name; // 用户名(对应请求参数 name) private Integer age; // 年龄(对应请求参数 age) private String email; // 邮箱(对应请求参数 email) // ⚠️ 必须有 getter/setter! // SpringMVC 通过反射调用 setXxx() 方法来赋值 // 没有 setter → 绑定失败,字段为 null public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } // toString 方便打印调试 @Override public String toString() { return "User{name='" + name + "', age=" + age + ", email='" + email + "'}"; } }
2

Controller 直接用对象接收

// 📄 UserController.java — POJO 绑定示例 package com.example.springmvcdemo.controller; import com.example.springmvcdemo.entity.User; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/user") public class UserController { // 注意: 参数类型直接写 User,不加任何注解 // SpringMVC 自动把请求参数按名称匹配到 User 对象的字段 // name=张三 → user.setName("张三") // age=20 → user.setAge(20) (自动类型转换: String → Integer) @PostMapping("/register") public String register(User user) { System.out.println("收到注册信息: " + user); return "注册成功!姓名: " + user.getName() + ", 年龄: " + user.getAge(); } }
3

用 Postman / curl 测试

# 方式1: URL 参数 curl "http://localhost:8080/user/register?name=张三&age=20&email=zhangsan@qq.com" -X POST # 方式2: 表单提交 curl -X POST http://localhost:8080/user/register \ -d "name=张三&age=20&email=zhangsan@qq.com" # 两种方式结果一样: # → "注册成功!姓名: 张三, 年龄: 20"

🎮 互动:看看数据是怎么"绑"上去的

点击按钮,模拟一个表单提交的绑定过程

等待模拟...

🎯 POJO 绑定的规则(超简单)

  • 请求参数名 name = 对象字段名 name名字一样就自动绑定
  • 类型自动转换:"20"(字符串)→ 20(Integer)
  • 没传的参数 → 字段值为 null
  • 对象必须有 setter 方法(或用 Lombok 的 @Data

3. @RequestBody —— 接收 JSON(最重要!)

现在的前后端分离项目,前端几乎都是传 JSON。怎么接?加一个注解就行!

1

Controller 加 @RequestBody

// 📄 UserApiController.java — 接收 JSON 请求 package com.example.springmvcdemo.controller; import com.example.springmvcdemo.entity.User; import org.springframework.web.bind.annotation.*; import java.util.*; @RestController @RequestMapping("/api/user") public class UserApiController { // @RequestBody: 从请求体中读取 JSON,自动转成 Java 对象 // 前端必须设置 Content-Type: application/json // Jackson 负责 JSON → Java 对象的转换 @PostMapping("/create") public Map<String, Object> createUser(@RequestBody User user) { System.out.println("收到JSON数据: " + user); // 构建响应(后续第3章会用统一的 Result 类替代) Map<String, Object> result = new HashMap<>(); result.put("code", 200); // 状态码 result.put("message", "创建成功"); // 提示信息 result.put("data", user); // 返回数据 return result; // Jackson 自动转成 JSON 返回前端 } }
2

用 Postman 测试(JSON 请求)

# 注意:必须设置 Content-Type: application/json curl -X POST http://localhost:8080/api/user/create \ -H "Content-Type: application/json" \ -d '{"name":"李四","age":25,"email":"lisi@qq.com"}' # 返回: { "code": 200, "message": "创建成功", "data": {"name": "李四", "age": 25, "email": "lisi@qq.com"} }
💡 @RequestBody vs 不加注解(POJO 绑定)的区别:
不加注解(POJO绑定) @RequestBody
数据来源 URL参数 / 表单 form-data 请求体 JSON
Content-Type application/x-www-form-urlencoded application/json
使用场景 传统表单提交 前后端分离(99%的场景)⭐

4. 文件上传(MultipartFile)

用户上传头像、上传 Excel —— 怎么接收文件?

1

配置文件大小限制(application.properties)

# 📄 application.properties # 单个文件最大 10MB spring.servlet.multipart.max-file-size=10MB # 总请求最大 50MB spring.servlet.multipart.max-request-size=50MB
2

写上传接口

// 📄 FileController.java — 文件上传接口 package com.example.springmvcdemo.controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.util.*; @RestController public class FileController { // 单文件上传 // @RequestParam("file"): 参数名必须和前端表单的 name 一致 // MultipartFile: Spring 封装的文件上传类型 @PostMapping("/upload") public Map<String, Object> upload(@RequestParam("file") MultipartFile file) { Map<String, Object> result = new HashMap<>(); // 第1步: 检查文件是否为空 if (file.isEmpty()) { result.put("code", 400); result.put("message", "文件不能为空!"); return result; } // 第2步: 获取文件信息 String fileName = file.getOriginalFilename(); // 原始文件名(如 "头像.jpg") long size = file.getSize(); // 文件大小(字节) String type = file.getContentType(); // MIME 类型(如 "image/jpeg") try { // 第3步: 保存到本地磁盘(实际项目会存到 OSS/MinIO 等对象存储) String savePath = "/tmp/uploads/" + fileName; file.transferTo(new java.io.File(savePath)); // 转存到指定路径 result.put("code", 200); result.put("message", "上传成功!"); result.put("fileName", fileName); result.put("size", size / 1024 + "KB"); } catch (Exception e) { result.put("code", 500); result.put("message", "上传失败: " + e.getMessage()); } return result; } // 多文件上传: 用数组 MultipartFile[] 接收 @PostMapping("/upload/batch") public String batchUpload(@RequestParam("files") MultipartFile[] files) { int count = 0; for (MultipartFile file : files) { if (!file.isEmpty()) { // 保存每个文件... count++; } } return "成功上传 " + count + " 个文件"; } }
3

用 Postman 测试

Postman → POST → http://localhost:8080/upload

Body → form-data → Key 输入 file,类型选 File → 选择一个文件 → Send

// 返回: { "code": 200, "message": "上传成功!", "fileName": "头像.jpg", "size": "156KB" }

🎯 MultipartFile 常用方法速查

getOriginalFilename() 原始文件名(如 "头像.jpg")
getSize() 文件大小(字节)
getContentType() 文件类型(如 "image/jpeg")
isEmpty() 文件是否为空
getBytes() 获取文件字节数组
transferTo(File) 保存到指定路径

5. 实战综合:一个完整的用户注册接口

把前面学的全用上!写一个能接收 JSON + 验证数据的注册接口。

📁 com.example.springmvcdemo
  📁 controller
    📄 UserController.java
  📁 entity
    📄 User.java
    📄 Result.java ← 统一响应格式
1

统一响应类 Result.java

// 📄 Result.java — 统一响应封装(所有接口都返回这个格式) package com.example.springmvcdemo.entity; // 泛型 T: data 字段可以是任意类型(User、List、String...) public class Result<T> { private int code; // 状态码: 200=成功, 400=参数错误 private String message; // 提示信息: "操作成功" / "姓名不能为空" private T data; // 返回的数据(成功时有数据,失败时为 null) // 成功: Result.success(数据) public static <T> Result<T> success(T data) { Result<T> r = new Result<>(); r.code = 200; // 200 表示成功 r.message = "操作成功"; r.data = data; // 把数据放进去 return r; } // 失败: Result.error("错误提示") public static <T> Result<T> error(String message) { Result<T> r = new Result<>(); r.code = 400; // 400 表示参数错误 r.message = message; // 自定义错误提示 return r; // data 为 null } // getter/setter(Jackson 需要这些方法来转 JSON) public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
2

完整的 UserController

// 📄 UserController.java — 完整的用户注册接口(串联本章所有知识点) package com.example.springmvcdemo.controller; import com.example.springmvcdemo.entity.*; import org.springframework.web.bind.annotation.*; import java.util.*; @RestController @RequestMapping("/api/user") public class UserController { // 模拟数据库(内存中的列表) private List<User> userDB = new ArrayList<>(); // 🟢 POST /api/user/register — 接收 JSON 注册 // @RequestBody: 解析请求体中的 JSON → User 对象 @PostMapping("/register") public Result<User> register(@RequestBody User user) { // 手动校验(第6章会学用注解自动校验) if (user.getName() == null || user.getName().isEmpty()) { return Result.error("姓名不能为空!"); // 返回错误信息 } if (user.getAge() != null && user.getAge() < 0) { return Result.error("年龄不能为负数!"); } userDB.add(user); // 存入"数据库" return Result.success(user); // 返回成功 + 用户数据 } // 🟢 GET /api/user/list — 查询所有用户 @GetMapping("/list") public Result<List<User>> list() { return Result.success(userDB); // 返回统一格式的用户列表 } // 🟢 GET /api/user/search?name=张 — 按名字模糊搜索 // @RequestParam: 从 URL 查询参数中取值 @GetMapping("/search") public Result<List<User>> search(@RequestParam String name) { List<User> found = userDB.stream() .filter(u -> u.getName().contains(name)) // 名字包含搜索词 .toList(); return Result.success(found); } }
3

测试!

# 1. 注册用户 curl -X POST http://localhost:8080/api/user/register \ -H "Content-Type: application/json" \ -d '{"name":"张三","age":20,"email":"zhangsan@qq.com"}' # → {"code":200,"message":"操作成功","data":{"name":"张三","age":20,...}} # 2. 查看所有用户 curl http://localhost:8080/api/user/list # → {"code":200,"data":[{"name":"张三","age":20,...}]} # 3. 搜索用户 curl "http://localhost:8080/api/user/search?name=张" # → {"code":200,"data":[{"name":"张三",...}]}

🎯 恭喜!你已经学会了:

  • @RequestBody 接收 JSON
  • @RequestParam 接收查询参数
  • ✅ POJO 自动绑定
  • ✅ 统一响应格式 Result<T>
  • ✅ 简单的参数校验

这就是真实项目中 90% 的数据接收方式

6. 章节闯关 🎯

第 1 关:前端传 JSON 数据,后端应该用什么注解接收?

第 2 关:POJO 绑定生效的关键条件是什么?

第 3 关:文件上传用什么类型接收?

本章小结

← 上一章: 入门 下一章: 响应数据 →