Spring Boot 4 深度解析——参数接收大全:@RequestParam、@PathVariable、@RequestBody

本篇是《Spring Boot 4 学习从入门到大神》专栏第 7 篇。

参数是接口的"入口",也是 Bug 的高发区。本文将系统讲解 Spring Boot 4 中各种参数接收方式、底层原理、复杂类型绑定、参数校验和常见坑位,帮你彻底搞定接口参数。


一、HTTP 请求参数到底在哪?

先建立一张全局认知图

参数位置 对应注解 示例
URL 路径 @PathVariable /users/{id}
URL 查询串 @RequestParam /users?id=1
请求体(JSON) @RequestBody { "name": "张三" }
请求头 @RequestHeader Authorization: Bearer xxx
Cookie @CookieValue JSESSIONID=xxx
表单 @RequestParam / @ModelAttribute username=zhangsan

📌 Spring Boot 4 的核心能力:自动从请求中"找"参数并绑定到方法参数。


二、@PathVariable:从 URL 路径中取参

1️⃣ 基本用法

复制代码
@GetMapping("/users/{id}")
public Result<UserVO> getUser(@PathVariable Long id) {
    return Result.success(userService.getById(id));
}

URL:

复制代码
GET /users/1

2️⃣ 指定变量名(推荐)

复制代码
@GetMapping("/users/{userId}")
public Result<UserVO> getUser(@PathVariable("userId") Long id) {
}

变量名不一致时必须指定


3️⃣ 多个路径参数

复制代码
@GetMapping("/companies/{companyId}/users/{userId}")
public Result<UserVO> getUser(
        @PathVariable Long companyId,
        @PathVariable Long userId) {
}

URL:

复制代码
GET /companies/1/users/10

4️⃣ 正则表达式约束(高级)

复制代码
@GetMapping("/users/{id:\\d+}")
public Result<UserVO> getUser(@PathVariable Long id) {
}

✅ 只匹配数字,非法请求直接 404


三、@RequestParam:从查询参数中取参

1️⃣ 基本用法

复制代码
@GetMapping("/users")
public Result<List<UserVO>> listUsers(
        @RequestParam String name,
        @RequestParam Integer age) {
}

URL:

复制代码
GET /users?name=zhangsan&age=18

2️⃣ 参数可选与默认值(非常重要)

复制代码
@GetMapping("/users")
public Result<List<UserVO>> listUsers(
        @RequestParam(defaultValue = "1") Integer page,
        @RequestParam(defaultValue = "10") Integer size,
        @RequestParam(required = false) String keyword) {
}

required = false:参数可缺省

defaultValue:参数不存在时的默认值


3️⃣ 接收数组 / List

复制代码
@GetMapping("/users")
public Result<List<UserVO>> listUsers(@RequestParam List<Long> ids) {
}

URL:

复制代码
GET /users?ids=1,2,3
GET /users?ids=1&ids=2&ids=3

四、@RequestBody:接收请求体(JSON)

1️⃣ 接收单个对象

复制代码
@PostMapping("/users")
public Result<UserVO> createUser(@RequestBody UserDTO dto) {
    return Result.success(userService.create(dto));
}

Body:

复制代码
{
  "username": "zhangsan",
  "age": 18,
  "email": "zs@test.com"
}

2️⃣ 接收 List / Map

复制代码
@PostMapping("/users/batch")
public Result<List<UserVO>> batchCreate(@RequestBody List<UserDTO> dtos) {
}

@PostMapping("/users/map")
public Result<?> save(@RequestBody Map<String, Object> map) {
}

3️⃣ JSON 字段与 Java 字段映射

复制代码
public record UserDTO(
        @JsonProperty("user_name") String username,
        Integer age
) {}

✅ 前端传 user_name,后端用 username


五、复杂对象绑定(非常实用)

1️⃣ 嵌套对象

复制代码
public record OrderDTO(
        Long id,
        UserDTO user,
        List<ItemDTO> items
) {}

JSON:

复制代码
{
  "id": 1001,
  "user": { "username": "zhangsan" },
  "items": [{ "name": "iPhone" }]
}

2️⃣ @RequestParam 绑定到对象(表单提交)

复制代码
@PostMapping("/users")
public Result<?> createUser(UserDTO dto) {
}

HTML 表单:

复制代码
<input name="username" value="zhangsan"/>
<input name="age" value="18"/>

📌 没有注解时,Spring 会按参数名从请求中查找


六、其他常用参数注解

1️⃣ @RequestHeader(请求头)

复制代码
@GetMapping("/users")
public Result<?> getUser(@RequestHeader("Authorization") String token) {
}

2️⃣ @CookieValue(Cookie)

复制代码
@GetMapping("/users")
public Result<?> getUser(@CookieValue("JSESSIONID") String sessionId) {
}

3️⃣ @MatrixVariable(矩阵参数,冷门但高级)

URL:

复制代码
/users/id=1;name=zhangsan;age=18

@GetMapping("/users/{id}")
public Result<?> getUser(@MatrixVariable String name) {
}

七、参数校验(JSR‑303,生产级必备)

1️⃣ 引入依赖

复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2️⃣ DTO 中加校验注解

复制代码
public record UserDTO(
        @NotBlank(message = "用户名不能为空")
        String username,

        @Min(value = 1, message = "年龄必须大于 0")
        Integer age,

        @Email(message = "邮箱格式不正确")
        String email
) {}

3️⃣ 开启校验

复制代码
@PostMapping("/users")
public Result<?> createUser(@Valid @RequestBody UserDTO dto) {
}

4️⃣ 统一异常处理(下篇会详细讲)

复制代码
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<?> handleValidException(MethodArgumentNotValidException e) {
        String msg = e.getBindingResult().getFieldError().getDefaultMessage();
        return Result.fail(400, msg);
    }
}

八、参数绑定的底层原理

Spring Boot 4 内部流程:

  1. DispatcherServlet 接收请求

  2. HandlerMapping 找到 Controller 方法

  3. HandlerAdapter 调用方法

  4. **参数解析器(HandlerMethodArgumentResolver)**​ 负责参数绑定

    • @PathVariablePathVariableMethodArgumentResolver

    • @RequestParamRequestParamMethodArgumentResolver

    • @RequestBodyRequestResponseBodyMethodProcessor

  5. 数据类型转换(Converter)

  6. 参数校验(Validator)

📌 一句话总结:

不同的注解,背后是不同的参数解析器。


九、常见坑位总结(血泪教训)

❌ 坑1:GET 请求用 @RequestBody

✅ GET 没有请求体


❌ 坑2:@RequestParam 接收 JSON

✅ JSON 必须用 @RequestBody


❌ 坑3:List 参数接收失败

✅ 要么用 @RequestParam List<Long> ids

✅ 要么用 @RequestBody List<Long> ids


❌ 坑4:参数校验不生效

✅ 忘记加 @Valid

✅ 忘记引入 spring-boot-starter-validation


❌ 坑5:前端传 null,后端用基本类型

复制代码
@RequestParam int age   // ❌
@RequestParam Integer age // ✅

十、本篇总结

  1. @PathVariable:URL 路径参数

  2. @RequestParam:查询参数 / 表单

  3. @RequestBody:JSON 请求体

  4. 参数校验用 JSR‑303 + @Valid

  5. 不同注解 = 不同参数解析器

相关推荐
NutShell Wang1 小时前
Rust 1.97 实战迁移:v0 符号重整、Cargo 警告治理与位运算新 API
人工智能·后端·性能优化·rust·vibe coding
阑梦清川1 小时前
零成本把笔记转成双人播客:WorkBuddy + 腾讯云 TTS 完整教程
后端
赫媒派1 小时前
Go 1.27 来了:泛型方法补齐,JSON 提速不踩坑
后端·go·敏捷开发
不ok哥男人1 小时前
C# Roslyn 编译器平台实战:源生成器、分析器与代码修补
后端
长栎1 小时前
99% 的人把桥接模式当策略模式用——抽象与实现分离,你做的不是同一件事
后端
长栎1 小时前
你激活了 sharp-skills 一个模块,但你的项目从来不是单点活儿
后端
(轻舟已过万重山)1 小时前
D1 · 融合蓝图:Spring AI + 虚拟线程 + 服务网格——现代后端统一底座
java·人工智能·spring
Lcos1 小时前
Kubernetes Toleration 六种写法详解:从精确匹配到全部放行
后端
元界metalite1 小时前
MyBatis事务只能靠Transactional吗-MetaLite为何只保留编程式事务
后端