前端传过来的数据,SpringMVC 怎么自动"接住"?
前端发来的请求就像一个快递包裹,上面贴着标签:name=张三、age=20、email=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、文件。
前端传了一堆参数,你不想一个一个 @RequestParam 接,怎么办?
直接定义一个 Java 对象,SpringMVC 自动帮你填好!
// 📄 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 + "'}";
}
}// 📄 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();
}
}# 方式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"点击按钮,模拟一个表单提交的绑定过程
name = 对象字段名 name → 名字一样就自动绑定"20"(字符串)→ 20(Integer)null@Data)现在的前后端分离项目,前端几乎都是传 JSON。怎么接?加一个注解就行!
// 📄 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 返回前端
}
}# 注意:必须设置 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"}
}| 不加注解(POJO绑定) | @RequestBody | |
| 数据来源 | URL参数 / 表单 form-data | 请求体 JSON |
| Content-Type | application/x-www-form-urlencoded | application/json |
| 使用场景 | 传统表单提交 | 前后端分离(99%的场景)⭐ |
用户上传头像、上传 Excel —— 怎么接收文件?
# 📄 application.properties
# 单个文件最大 10MB
spring.servlet.multipart.max-file-size=10MB
# 总请求最大 50MB
spring.servlet.multipart.max-request-size=50MB// 📄 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 + " 个文件";
}
}Postman → POST → http://localhost:8080/upload
Body → form-data → Key 输入 file,类型选 File → 选择一个文件 → Send
// 返回:
{
"code": 200,
"message": "上传成功!",
"fileName": "头像.jpg",
"size": "156KB"
}getOriginalFilename() |
原始文件名(如 "头像.jpg") |
getSize() |
文件大小(字节) |
getContentType() |
文件类型(如 "image/jpeg") |
isEmpty() |
文件是否为空 |
getBytes() |
获取文件字节数组 |
transferTo(File) |
保存到指定路径 |
把前面学的全用上!写一个能接收 JSON + 验证数据的注册接口。
// 📄 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; }
}// 📄 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);
}
}# 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 接收查询参数Result<T>这就是真实项目中 90% 的数据接收方式!
?key=value/user/{id}