源本科技 | 码上会

@PathVariable & @RequestParam

2026/03/30
14
0

引言

在 Spring Boot 开发 RESTful API 时,@PathVariable@RequestParam 是从 URL 中获取参数的两大核心注解,也是控制器方法中最常用的参数绑定注解。 二者的核心分工遵循 RESTful 设计规范:@PathVariable 用于定位资源@RequestParam 用于筛选 / 过滤资源,清晰的分工能让接口语义更明确、代码更规范。


@PathVariable

核心定义

用于绑定 URL 路径中的动态占位符 到方法参数,唯一作用是定位服务器资源(如用户 ID、订单编号),是 RESTful 风格的标志性注解。 数据来源:URL 路径本体(非 ? 后的参数)。

核心特性

  • 用于标识唯一资源,不可或缺

  • 默认必填,缺失会直接返回 404 错误

  • 不支持默认值(Spring 4.3+ 可通过配置实现可选)

  • 支持正则表达式限制参数格式

  • Spring 自动完成类型转换(String → Long/Integer/UUID 等)

基础语法

  1. 占位符与参数名一致:@PathVariable Long id

  2. 名称不一致:@PathVariable("userId") Long id

  3. 多路径变量:/users/{userId}/orders/{orderId}

代码示例

@RestController
@RequestMapping("/api/users")
public class UserController {

    // 1. 基础用法:根据ID查询用户 GET /api/users/1001
    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userService.getById(id);
        return ResponseEntity.ok(user);
    }

    // 2. 多路径变量:查询用户的指定订单 GET /api/users/1001/orders/2002
    @GetMapping("/{userId}/orders/{orderId}")
    public ResponseEntity<Order> getUserOrder(
            @PathVariable Long userId,
            @PathVariable Long orderId
    ) {
        Order order = orderService.getByUserIdAndOrderId(userId, orderId);
        return ResponseEntity.ok(order);
    }

    // 3. 正则限制:仅允许数字ID(防止非法参数)
    @GetMapping("/{id:\\d+}")
    public ResponseEntity<User> getUserByRegex(@PathVariable Long id) {
        return ResponseEntity.ok(userService.getById(id));
    }
}

@RequestParam

核心定义

用于绑定 URL 查询字符串(? 后的键值对) 到方法参数,用于对资源进行筛选、分页、排序、搜索,不负责定位资源。 数据来源:?key=value&key2=value2

核心特性

  • 用于辅助查询,支持可选参数

  • 可配置 required:是否必填(默认 true

  • 支持 defaultValue:设置默认值

  • 支持接收数组、集合(多值参数)

  • 缺失必填参数会返回 400 错误

基础语法

  1. 参数名一致:@RequestParam String name

  2. 可选参数:@RequestParam(required = false) String name

  3. 带默认值:@RequestParam(defaultValue = "1") Integer page

  4. 多值参数:@RequestParam List<Long> ids

代码示例

@RestController
@RequestMapping("/api/users")
public class UserController {

    // 1. 基础必填参数:按姓名搜索 GET /api/users/search?name=张三
    @GetMapping("/search")
    public ResponseEntity<List<User>> searchUser(@RequestParam String name) {
        return ResponseEntity.ok(userService.findByName(name));
    }

    // 2. 可选+默认值:分页查询 GET /api/users/page
    @GetMapping("/page")
    public ResponseEntity<Page<User>> pageQuery(
            // 可选参数,无默认值
            @RequestParam(required = false) String keyword,
            // 必填,默认值1
            @RequestParam(defaultValue = "1") Integer page,
            // 必填,默认值10
            @RequestParam(defaultValue = "10") Integer size
    ) {
        return ResponseEntity.ok(userService.page(keyword, page, size));
    }

    // 3. 多值参数:批量查询 GET /api/users/batch?ids=1,2,3
    @GetMapping("/batch")
    public ResponseEntity<List<User>> batchGet(@RequestParam List<Long> ids) {
        return ResponseEntity.ok(userService.listByIds(ids));
    }
}

核心区别

特性

@PathVariable

@RequestParam

数据位置

URL 路径本体(无 ?)

URL 查询字符串(? 之后)

核心用途

定位唯一资源(ID/ 唯一标识)

筛选 / 分页 / 排序 / 搜索(辅助条件)

必填性

默认强制必填,缺失返回 404

默认必填,可设 required=false 可选

默认值

不支持原生默认值

支持 defaultValue 设置默认值

多值支持

不支持

支持数组 /List 接收多值参数

错误类型

路径不匹配 → 404 Not Found

参数缺失 / 格式错误 → 400 Bad Request

正则支持

支持限制参数格式

不支持

URL 编码

不支持特殊字符(如 /)

支持自动编码解码

适用请求

GET/DELETE/PUT 等所有请求

所有请求(GET 最常用)

RESTful 语义

符合标准资源定位

符合标准资源过滤


混合使用

实际开发中,资源定位 + 条件筛选 是最常用的组合方式:

示例:查询指定用户的已支付订单(路径变量定位用户,查询参数筛选订单状态)

@RestController
@RequestMapping("/api/users")
public class OrderController {

    /**
     * 请求地址:GET /api/users/1001/orders?status=PAID&page=1&size=5
     * 路径变量:userId=1001
     * 查询参数:status=PAID、page=1、size=5
     */
    @GetMapping("/{userId}/orders")
    public ResponseEntity<Page<Order>> getUserOrders(
            @PathVariable Long userId,
            @RequestParam String status,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "5") Integer size
    ) {
        Page<Order> orders = orderService.getUserOrders(userId, status, page, size);
        return ResponseEntity.ok(orders);
    }
}

其他补充

可选的路径变量

@PathVariable 原生不支持默认值,但可通过可选占位符实现:

// 匹配 /users 或 /users/1001
@GetMapping({"/users", "/users/{id}"})
public ResponseEntity<List<User>> getUsers(@PathVariable(required = false) Long id) {
    if (id == null) return ResponseEntity.ok(userService.listAll());
    return ResponseEntity.ok(Collections.singletonList(userService.getById(id)));
}

省略注解的情况

在 Spring Boot 2.0+ 中,参数名与占位符 / 查询参数名一致时,可省略注解

// 等价 @PathVariable Long id
@GetMapping("/{id}")
public User getUser(Long id) { ... }

// 等价 @RequestParam String name
@GetMapping("/search")
public List<User> search(String name) { ... }

参数类型转换与异常处理

Spring 会自动将 URL 中的字符串转换为目标类型(Long/Integer/UUID 等),转换失败抛出 TypeMismatchException,可通过全局异常处理统一返回:

@ExceptionHandler(TypeMismatchException.class)
public ResponseEntity<String> handleTypeError() {
    return ResponseEntity.badRequest().body("参数格式错误!");
}

与 @RequestBody 区分

  • @PathVariable/@RequestParam:从 URL 取参,适合简单参数

  • @RequestBody:从 请求体 取参,适合复杂 JSON 对象


总结

  1. 核心分工 @PathVariable = 定位资源(URL 路径),@RequestParam = 筛选资源(URL 查询参数);

  2. 使用规则 定位用路径变量、筛选用查询参数,二者配合实现标准 RESTful 接口;

  3. 关键特性 路径变量必填无默认值、查询参数可选支持默认值,错误类型分别为 404/400;

  4. 开发规范 保留注解提升可读性,严格校验参数,不传递敏感数据,让接口更规范、更安全。