乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 SpringMVC概述与DispatcherServlet

    • 本章导读:Spring MVC概述与DispatcherServlet
    • Spring MVC 是什么
    • MVC 设计模式
    • 前端控制器模式
    • DispatcherServlet
    • 核心组件协作
  • 第2章 控制器与请求映射

    • 本章导读:控制器与请求映射
    • Controller
    • RestController
    • RequestMapping
    • GetMapping
    • PostMapping
    • PutMapping
    • DeleteMapping
    • PathVariable
    • RESTful
    • 请求映射原理
  • 第3章 请求参数获取与转换

    • 本章导读:请求参数获取与转换
    • RequestParam
    • RequestBody
    • RequestHeader
    • CookieValue
    • Model
    • ModelAttribute
    • 数据绑定原理
    • 数据校验
  • 第4章 响应数据与视图解析

    • 本章导读:响应数据与视图解析
    • ResponseBody
    • ResponseEntity
    • ModelAndView
    • ViewResolver
    • HttpMessageConverter
    • forward与redirect
  • 第5章 拦截器过滤器与跨域

    • 本章导读:拦截器、过滤器与跨域
    • HandlerInterceptor
    • WebMvcConfigurer
    • CrossOrigin
    • 登录验证实战
  • 第6章 文件上传与异常处理

    • 本章导读:文件上传与异常处理
    • MultipartFile
    • 文件下载
    • ExceptionHandler
    • ControllerAdvice
    • RestControllerAdvice
    • ResponseStatus
  • 第7章 高级特性与最佳实践

    • 本章导读:高级特性与最佳实践
    • SessionAttributes
    • SessionAttribute
    • RedirectAttributes
    • MockMvc测试
    • 国际化
    • 最佳实践
  • 第8章 扩展与异步机制

    • 本章导读:扩展与异步机制
    • 异步请求处理
    • 自定义参数解析器
    • 内容协商

PathVariable

本章是 Spring MVC RESTful URL 设计的核心。在 RESTful 架构中,资源通过 URL 路径直接定位,如 /employees/1001 表示 ID 为 1001 的员工。@PathVariable 的作用就是将 URL 路径中的模板变量绑定到 Controller 方法的参数上。理解 @PathVariable,就掌握了 RESTful 风格 URL 的参数提取机制。


定义与作用

@PathVariable 是 Spring MVC 提供的方法参数级注解,它的职责可以用一句话概括:将 URL 路径中的模板变量(占位符)绑定到 Controller 方法的形参上,实现 RESTful 风格的资源定位。

在 RESTful 设计中,URL 是资源的地址,不是操作的地址:

  • 传统风格:/getEmployee?id=1001(URL 描述操作,参数描述目标)
  • RESTful 风格:/employees/1001(URL 直接定位资源)

@PathVariable 让 Spring MVC 能够解析第二种风格的 URL。


核心原理

URL 模板变量解析过程

图解:

  1. HandlerMapping 匹配 URL 模式 /employees/{id} 与实际路径 /employees/1001
  2. 提取路径变量 id=1001(字符串形式)
  3. HandlerAdapter 调用方法时,根据 @PathVariable 的声明,将字符串转换为方法参数类型(Long)
  4. 类型转换失败时(如 /employees/abc),抛出 MethodArgumentTypeMismatchException,最终返回 400 Bad Request

@PathVariable 与 @RequestParam 的对比


适用位置与常用属性

@PathVariable 标注在方法参数上,有以下属性:

属性类型作用示例
value / nameString指定路径变量名(与形参名不一致时使用)@PathVariable("id") Long employeeId
requiredboolean是否必须(默认 true)@PathVariable(required = false) Long id

@PathVariable vs @RequestParam 对比表

对比维度@PathVariable@RequestParam
参数位置URL 路径中URL 查询字符串中
URL 示例/employees/1001/employees?id=1001
风格RESTful传统
是否必填是(路径必须有值)可配置(默认必填)
支持多个值否(一个占位符一个值)是(?id=1&id=2)
适合场景资源标识符查询条件、过滤参数
正则限定支持({id:\d+})不支持

完整示例

场景

飞翔科技的员工管理系统采用 RESTful 设计。架构师白歌要求所有资源定位都使用路径变量风格,如 /employees/1001、/departments/2001。

控制器代码

package com.feixiang.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/employees")
public class EmployeeController {

    // 容器已注入该 Bean,本教程不展开 Service 实现
    @Autowired
    private EmployeeService employeeService;

    // 基础用法:单个路径变量
    @GetMapping("/{id}")
    public Employee getById(@PathVariable Long id) {
        return employeeService.findById(id);
    }

    // 显式指定变量名(形参名与占位符不一致)
    @GetMapping("/{id}/manager")
    public Employee getManager(@PathVariable("id") Long employeeId) {
        return employeeService.findManager(employeeId);
    }

    // 多个路径变量
    @GetMapping("/{id}/projects/{projectId}")
    public Project getEmployeeProject(
            @PathVariable Long id,
            @PathVariable Long projectId) {
        return employeeService.findProject(id, projectId);
    }

    // 正则限定:只匹配数字 ID
    @GetMapping("/{id:\d+}")
    public Employee getByNumericId(@PathVariable Long id) {
        return employeeService.findById(id);
    }

    // 组合路径变量和查询参数
    @GetMapping("/{id}/tasks")
    public List<Task> getTasks(
            @PathVariable Long id,
            @RequestParam(required = false) String status) {
        return employeeService.findTasks(id, status);
    }
}

HTTP 请求示例 1:单个路径变量

curl -X GET http://localhost:8080/employees/1001 \
  -H "Accept: application/json"

实际响应:

{
  "id": 1001,
  "name": "张伟",
  "department": "技术部",
  "position": "高级工程师"
}

分析:

  • URL /employees/1001 匹配 @GetMapping("/{id}")
  • 路径变量 id=1001 被提取并转换为 Long
  • 如果访问 /employees/abc,类型转换失败,返回 400 Bad Request

HTTP 请求示例 2:多个路径变量 + 查询参数

curl -X GET "http://localhost:8080/employees/1001/tasks?status=进行中" \
  -H "Accept: application/json"

实际响应:

[
  {
    "taskId": 5001,
    "title": "API 接口开发",
    "status": "进行中",
    "deadline": "2024-07-01"
  },
  {
    "taskId": 5002,
    "title": "单元测试编写",
    "status": "进行中",
    "deadline": "2024-06-30"
  }
]

分析:

  • 1001 是路径变量(@PathVariable),标识资源
  • status=进行中 是查询参数(@RequestParam),标识过滤条件
  • RESTful 设计原则:资源标识符放路径,查询条件放查询字符串
  • 这种混合使用是实际项目中最常见的模式

易错场景与面试考点

误区一:路径变量名与占位符不一致

错误写法:

@GetMapping("/{employeeId}")
public Employee getById(@PathVariable Long id) {
    // 编译错误!占位符是 employeeId,参数名是 id
    return employeeService.findById(id);
}

纠正:如果方法参数名与 URL 占位符名不一致,必须显式指定 value:

@GetMapping("/{employeeId}")
public Employee getById(@PathVariable("employeeId") Long id) {
    return employeeService.findById(id);
}

注意:如果编译时保留了参数名(Java 8+ 加 -parameters 编译选项,或 IDE 默认开启),Spring 可以自动匹配。但生产环境建议显式指定,避免编译优化导致参数名丢失。

误区二:用 @PathVariable 做可选参数

错误写法:

@GetMapping("/{id}")
public Employee getById(@PathVariable(required = false) Long id) {
    if (id == null) {
        return employeeService.findDefault();
    }
    return employeeService.findById(id);
}

纠正:@PathVariable(required = false) 虽然语法上可行,但 RESTful 设计上路径变量应该是必填的。可选参数应该使用 @RequestParam 或设计不同的 URL 模式:

// 方案一:分开设计
@GetMapping("/default")
public Employee getDefault() {
    return employeeService.findDefault();
}

@GetMapping("/{id}")
public Employee getById(@PathVariable Long id) {
    return employeeService.findById(id);
}

// 方案二:使用查询参数
@GetMapping
public Employee getById(@RequestParam(required = false) Long id) {
    if (id == null) {
        return employeeService.findDefault();
    }
    return employeeService.findById(id);
}

面试高频:@PathVariable 与 @RequestParam 的区别

标准回答:

  • @PathVariable 绑定 URL 路径中的模板变量,如 /employees/1001 中的 1001,用于 RESTful 资源定位
  • @RequestParam 绑定 URL 查询字符串中的参数,如 /employees?id=1001 中的 1001,用于查询条件
  • @PathVariable 通常必填(路径必须有值),@RequestParam 可配置是否必填
  • @PathVariable 支持正则限定({id:\d+}),@RequestParam 不支持
  • RESTful 设计中,资源标识符用 @PathVariable,过滤/排序/分页参数用 @RequestParam

小结

@PathVariable 是 Spring MVC 实现 RESTful URL 的核心注解,它将 URL 路径中的模板变量绑定到方法参数,使 URL 可以直接定位资源。它是 RESTful 风格与传统风格的分水岭,与 @RequestParam 形成互补:资源标识符走路径,查询条件走查询字符串。

本章与全局的关系:本章讲解了 RESTful URL 的参数绑定机制。至此,第 2 章"控制器与请求映射"的核心注解(@Controller、@RestController、@RequestMapping、@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PathVariable)已全部讲解完毕。后续章节将深入讲解请求参数获取、响应数据与视图解析、RESTful API 与消息转换等主题。

上一页
DeleteMapping
下一页
RESTful