@RequestParam:获取"路径参数"
它是用来处理 URL 问号后面 跟着的参数,或者是 Form 表单提交的字段。
-
场景 :
http://localhost:8080/api/student?name=张三&age=18 -
用法:
Java
@GetMapping("/student") public String getStudent( @RequestParam("name") String stuName, // 匹配 URL 里的 name @RequestParam(value = "age", required = false, defaultValue = "0") int stuAge // 可选,有默认值 ) { return "姓名:" + stuName + ",年龄:" + stuAge; } -
注意 :如果不加这个注解,Spring 其实也能根据变量名自动匹配,但加上它会更清晰,且可以设置
required=true强制要求前端传参。
2. @RequestBody:获取"JSON 对象"
它是用来处理 请求体(Body) 里的数据。现在流行的前后端分离(如 Vue + Java),前端发送 axios.post 时,数据通常是以 JSON 格式传过来的,必须用它。
-
场景 :前端发来一个 JSON 字符串
{"name": "李四", "age": 20}。 -
用法:
Java
@PostMapping("/add") public String addStudent(@RequestBody Student student) { // Spring 会自动把 JSON 里的字段映射到 Student 对象的属性上 System.out.println(student.getName()); return "添加成功"; } -
注意 :一个方法里只能有一个
@RequestBody。
3. @ResponseBody:返回"纯数据"
这个注解告诉 Spring:不要去找什么 HTML 页面,直接把返回的对象转成 JSON 丢回给前端。
-
用法:
Java
@GetMapping("/info") @ResponseBody public Student getInfo() { return new Student("王五", 22); // 前端收到的是 {"name":"王五", "age":22} } -
进阶 :如果你在类名上写的是
@RestController,那么类里所有的方法都默认带了@ResponseBody,你就不用重复写了。这也是现在最主流的写法。
💡 总结对比:一图胜千言
| 注解 | 数据来源 | 数据格式 | 对应 HTTP 方法 |
|---|---|---|---|
| @RequestParam | URL 问号后或表单 | 键值对 (Key-Value) | 通常是 GET / POST |
| @RequestBody | 请求体 (Body) | JSON / XML | 通常是 POST / PUT |
| @ResponseBody | 方法返回值 | JSON (转换后) | 所有 |
🚩 避坑小指南
-
传对象用哪个? 如果前端用
application/json传大对象,用@RequestBody;如果前端只是传几个简单的散参数,用@RequestParam。 -
415 错误 :如果你用了
@RequestBody,但前端没设置Content-Type: application/json,你会收到一个415 Unsupported Media Type。 -
400 错误 :如果
@RequestParam设置了required=true(默认就是 true),但前端没传这个参数,就会报 400 错误。
想象一下,你正在做一个学生管理系统:
-
你需要通过 JSON 提交一堆学生资料(姓名、年龄、住址等)。
-
同时,你可能还需要额外传一个参数,比如
operator(是谁在操作)或者updateLog(是否记录日志)。
这时候,主数据走 Body,额外的小参数走 URL,逻辑非常清晰。
2. 代码演练:双剑合璧
假设我们要修改学生信息,同时指定修改的原因:
Java
@PutMapping("/update")
public String updateStudent(
// 1. 接收 JSON 格式的学生对象 (Body)
@RequestBody Student student,
// 2. 接收 URL 拼接的参数 (URL ?reason=...)
@RequestParam("reason") String reason,
// 3. 甚至还可以再带一个参数
@RequestParam(value = "adminId", required = false) Integer adminId
) {
System.out.println("修改的学生是:" + student.getName());
System.out.println("修改原因是:" + reason);
return "更新成功!";
}
3. 前端怎么调用?(关键点)
这是最容易翻车的地方。前端在发送请求时,数据是"兵分两路"的。
以 Axios 为例:
JavaScript
axios.put('/update?reason=毕业信息修改&adminId=99', {
// 这里的对象会进入 @RequestBody
id: 1,
name: "张三",
age: 22
})
.then(res => console.log(res.data));
-
URL 部分 :
/update?reason=xxx&adminId=99------ 对应@RequestParam。 -
Data 部分 :
{ id: 1, name: "张三" ... }------ 对应@RequestBody。
4. 使用总结与注意事项
| 维度 | @RequestBody | @RequestParam |
|---|---|---|
| 位置 | 放在 HTTP 请求体(Body) | 放在 URL 后面(Query String) |
| 数量限制 | 一个方法只能有一个 | 可以有多个 |
| 数据量 | 适合传输复杂的大对象 | 适合传输简单的短字符串/数字 |
| Content-Type | 必须是 application/json |
无所谓(通常是 text/plain) |
🚩 避坑指南:
-
别搞混了 :如果你把
reason也写进 JSON 里,那么 Java 端的@RequestParam("reason")是拿不到值的,它只会去 URL 后面找。 -
GET 请求的限制 :虽然 HTTP 协议理论上允许 GET 请求带 Body,但绝大多数 服务器和框架(包括老版本的 Spring)不支持 GET 请求使用
@RequestBody。所以这种组合通常出现在 POST、PUT、PATCH 方法中。 -
大杂烩写法:如果参数实在太多,有时候我们会直接在 Body 的对象里增加字段,但这会污染你的"学生类(Entity)"。所以,灵活混用这两者才是老手的做法。
老弟,学会这招,你就能处理那种"主数据+控制参数"的复杂业务了。看你现在对 Java 框架钻研得这么深,是不是觉得比起捏 3D 模型,这种"数据流转"的逻辑美感也挺有意思的?