获取 HTTP 请求参数是非常常见的操作。无论你是做 REST API 还是传统 Web 表单,都需要从请求中提取数据。
🌟 一、总体分类:5 种常见参数来源
| 参数类型 | 说明 | 注解 |
|---|---|---|
| 1. 路径参数 | URL 中的动态部分,如 /user/123 中的 123 |
@PathVariable |
| 2. 查询参数 | URL 问号后的参数,如 /search?name=张三 |
@RequestParam |
| 3. 请求体(Body) | POST/PUT 请求中发送的 JSON、XML、表单等数据 | @RequestBody |
| 4. 表单参数 | HTML 表单提交的 application/x-www-form-urlencoded 数据 |
@RequestParam(或直接用对象) |
| 5. 请求头(Header) | 如 Authorization: Bearer xxx |
@RequestHeader |
🔹 1. 路径参数:@PathVariable
用于获取 URL 路径中的动态值。
✅ 示例:
@GetMapping("/user/{id}")
public String getUser(@PathVariable Long id) {
return "用户ID是:" + id;
}
- 请求:
GET /user/1001 - 结果:
用户ID是:1001
⚠️ 注意:
{id}必须和@PathVariable的参数名一致,或显式指定:@PathVariable("id")
🔹 2. 查询参数:@RequestParam
用于获取 URL 中 ? 后面的参数(Query String)。
✅ 示例:
@GetMapping("/search")
public String search(@RequestParam String keyword,
@RequestParam(defaultValue = "10") int size) {
return "搜索关键词:" + keyword + ",返回数量:" + size;
}
- 请求:
GET /search?keyword=手机&size=20 - 结果:
搜索关键词:手机,返回数量:20
📌 常用选项:
-
required = false:参数可选 -
defaultValue = "xxx":默认值(自动类型转换)@RequestParam(required = false, defaultValue = "1") int page
💡 如果参数名和方法参数名一致,
@RequestParam可省略(但建议保留,更清晰)。
参数如果多了,也可以绑定到实体上
1.定义查询参数实体类
public class UserQuery {
private String name;
private Integer age;
private String email;
private Integer page = 1; // 默认值
private Integer size = 10;
// 必须提供 getter/setter(Lombok 可简化)
public String getName() { return name; }
public void setName(String name) { this.name = name; }
// ... 其他 getter/setter
}
💡 注意 :必须有 setter 方法,Spring 才能通过反射赋值。
2. Controller 中直接使用该实体(无需注解!)
@GetMapping("/users")
public List<User> searchUsers(UserQuery query) {
System.out.println("查询条件: " + query.getName() + ", 年龄: " + query.getAge());
// 调用 service 查询...
return userService.search(query);
}
✅ 关键点 :不需要加
@RequestParam或@RequestBody!Spring 会自动将
?name=张三&age=25&page=2绑定到UserQuery对象。
3. 测试请求
GET /users?name=张三&age=25&email=zhangsan@example.com&page=2&size=20
Spring 会自动创建 UserQuery 实例,并调用:
setName("张三")setAge(25)setEmail("zhangsan@example.com")setPage(2)setSize(20)
🔹 3. 请求体(JSON):@RequestBody
用于接收 POST/PUT 请求中的 JSON 数据(最常见于 REST API)。
✅ 示例:
@PostMapping("/user")
public String createUser(@RequestBody User user) {
return "创建用户:" + user.getName();
}
public class User {
private String name;
private int age;
// getter/setter
}
-
请求(Content-Type: application/json):
POST /user { "name": "李四", "age": 25 } -
结果:
创建用户:李四
✅ Spring Boot 默认用 Jackson 自动把 JSON 转成 Java 对象。
❌ 不能用于 GET 请求(GET 没有请求体)。
🔹 4. 表单参数(传统 Web 表单)
HTML 表单提交的数据(Content-Type: application/x-www-form-urlencoded),Spring 会自动绑定到对象或参数。
方式一:用对象自动绑定(推荐)
@PostMapping("/login")
public String login(UserForm form) { // 不需要注解!
return "用户名:" + form.getUsername();
}
public class UserForm {
private String username;
private String password;
// getter/setter
}
表单:
<form action="/login" method="post">
<input name="username" value="admin">
<input name="password" value="123">
<button type="submit">登录</button>
</form>
方式二:用 @RequestParam 一个个取
@PostMapping("/login")
public String login(@RequestParam String username,
@RequestParam String password) {
// ...
}
💡 表单参数和查询参数都用
@RequestParam,Spring 会自动区分来源。如果参数名和方法参数名一致,
@RequestParam可省略(但建议保留,更清晰)。
🔹 5. 请求头(Header):@RequestHeader
获取 HTTP 请求头中的信息,比如 Token、语言偏好等。
✅ 示例:
@GetMapping("/profile")
public String profile(@RequestHeader("Authorization") String auth) {
return "Token 是:" + auth;
}
-
请求头:
Authorization: Bearer abc123xyz -
结果:
Token 是:Bearer abc123xyz
可选 + 默认值:
@RequestHeader(value = "Accept-Language", defaultValue = "zh-CN") String lang
🔸 特殊情况:获取原始请求对象
如果你需要更底层的操作,可以直接注入:
@GetMapping("/raw")
public void handle(HttpServletRequest request,
HttpServletResponse response) {
String ip = request.getRemoteAddr();
// 直接操作 request/response
}
但一般不推荐,除非做特殊处理(如文件下载、自定义响应流)。
✅ 总结
| 参数类型 | 是否可省略注解 | 条件 | 示例 |
|---|---|---|---|
| 简单类型(String/int 等) | ✅ 可省略 @RequestParam |
参数名 = 请求参数名 | String name |
| 复杂对象(POJO) | ✅ 可省略所有注解 | 表单/查询参数,字段名匹配 | UserForm form |
| JSON 对象 | ❌ 不可省略 @RequestBody |
必须显式声明 | @RequestBody User user |
| 路径变量 | ❌ 不可省略 @PathVariable |
必须显式声明 | @PathVariable Long id |
| 请求头 | ❌ 不可省略 @RequestHeader |
必须显式声明 | @RequestHeader String token |
使用 Map 接收请求参数
尤其适用于:
- 参数结构动态不确定(比如第三方回调、表单字段不固定)
- 不想定义专门的 POJO 类
- 快速原型开发或调试
下面详细讲解 如何用 Map 接收各种请求参数,以及注意事项。
一、用 Map 接收表单或查询参数(最常见)
场景:application/x-www-form-urlencoded 或 URL 查询参数
@PostMapping("/submit")
public String handleForm(@RequestParam Map<String, String> params) {
// params 会自动包含所有表单字段
String name = params.get("username");
String email = params.get("email");
return "收到参数: " + params;
}
✅ 请求(表单或 curl):
curl -X POST http://localhost:8080/submit \ -d "username=alice&email=a@example.com&age=25"→
params = {username=alice, email=a@example.com, age=25}
🔍 关键点:
- 必须加
@RequestParam!
如果写成Map<String, String> params(无注解),Spring 会认为你想用@RequestBody,从而报错。 - 值类型是
String:所有参数值都会被转为字符串(即使传的是数字"25")。 - 支持多值吗 ? ❌
Map<String, String>只取第一个值。如果需要多值,用MultiValueMap(见下文)。
二、用 Map 接收 JSON 请求体(动态 JSON)
如果你收到的是 结构不固定的 JSON ,也可以用 Map 接收:
@PostMapping("/dynamic-json")
public String handleJson(@RequestBody Map<String, Object> payload) {
// payload 是解析后的 JSON 对象
String name = (String) payload.get("name");
Integer age = (Integer) payload.get("age");
return "JSON 内容: " + payload;
}
✅ 请求:
curl -X POST http://localhost:8080/dynamic-json \ -H "Content-Type: application/json" \ -d '{"name":"Bob","age":30,"tags":["java","spring"]}'→
payload = {name=Bob, age=30, tags=[java, spring]}
🔍 关键点:
- 必须加
@RequestBody - 值类型是
Object,可以是String、Number、List、嵌套Map等 - Spring 使用 Jackson 自动将 JSON 转为
Map<String, Object>
三、高级用法:接收多值参数(如 ?tag=A&tag=B)
如果同一个参数名出现多次(如复选框),用 Map 会丢失数据。此时应使用 MultiValueMap:
@GetMapping("/search")
public String search(@RequestParam MultiValueMap<String, String> params) {
List<String> tags = params.get("tag"); // 可能是 ["A", "B"]
return "标签: " + tags;
}
✅ 请求:
/search?tag=Java&tag=Spring→tags = ["Java", "Spring"]
💡MultiValueMap是 Spring 提供的接口,常用实现是LinkedMultiValueMap。
常见误区与注意事项
| 问题 | 正确做法 |
|---|---|
写成 Map params(无注解) |
❌ Spring 无法判断来源,会报错 |
期望 Map<String, Integer> 自动转数字 |
❌ 表单/查询参数中 Map 的值永远是 String |
用 Map 接收 JSON 但忘记 @RequestBody |
❌ 必须加 @RequestBody |
用 Map 接收路径变量 |
❌ 路径变量只能用 @PathVariable |
完整示例代码
@RestController
public class MapParamController {
// 1. 接收表单/查询参数
@PostMapping("/form-map")
public Map<String, String> handleForm(@RequestParam Map<String, String> params) {
return params;
}
// 2. 接收动态 JSON
@PostMapping("/json-map")
public Map<String, Object> handleJson(@RequestBody Map<String, Object> payload) {
return payload;
}
// 3. 接收多值参数
@GetMapping("/multi")
public List<String> handleMulti(@RequestParam MultiValueMap<String, String> params) {
return params.get("item");
}
}
什么时候该用 Map?
| 场景 | 推荐 |
|---|---|
| 参数结构固定、已知 | ❌ 用 POJO(类型安全、可校验) |
| 第三方回调(如支付通知) | ✅ 用 Map 快速接收 |
| 前端传动态表单(字段不固定) | ✅ 用 @RequestParam Map |
| 调试或临时接口 | ✅ 用 Map 省去定义类 |
| 需要参数校验(@Valid) | ❌ Map 无法使用 Bean Validation |
总结
| 请求类型 | 接收方式 | 注解 |
|---|---|---|
| 表单 / 查询参数 | Map<String, String> |
@RequestParam |
| JSON 动态对象 | Map<String, Object> |
@RequestBody |
| 多值参数 | MultiValueMap<String, String> |
@RequestParam |
✅ 记住:
- 表单/查询 →
@RequestParam Map- JSON →
@RequestBody Map- 永远不要省略注解!
用好 Map,让你的接口更灵活;用好 POJO,让你的代码更健壮。根据场景选择即可!