Skip to content

映射请求 (Mapping Requests)

你可以使用 @RequestMapping 注解将请求映射到控制器方法。它具有各种属性,可通过 URL、HTTP 方法、请求参数、标头和媒体类型进行匹配。你可以在类级别使用它来表达共享映射,或在方法级别使用它来缩小到特定的端点映射。

快捷变体

常见的 HTTP 方法都有对应的快捷注解:

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping

这些变体是组合注解,因为大多数控制器方法应该映射到特定的 HTTP 方法,而不是使用默认匹配所有方法的 @RequestMapping。类级别仍需使用 @RequestMapping 来表达共享路径。

URI 模式 (URI Patterns)

Spring MVC 使用 PathPattern 来匹配请求。

  • Glob 模式:支持 ?(匹配一个字符)、*(路径段内匹配)、**(匹配零或多个路径段)。
  • 变量捕获:使用 {name} 捕获路径变量,通过 @PathVariable 访问。
  • 正则表达式:使用 {name:regex} 格式,如 /{name:[a-z-]+}

注意

AntPathMatcher 现已弃用,因为它在处理编码和 URL 复杂性时效率较低。推荐使用 Spring 6.0 默认启用的 PathPatternParser

模式详细说明

模式描述示例
spring字面量模式/spring 匹配 /spring
?匹配一个字符/t?st 匹配 /test/t3st
*路径段内匹配/resources/*.png 匹配 /resources/file.png
**匹配多个路径段/resources/** 匹配 /resources/file.png/resources/a/b/c.png
{name}变量捕获/owners/{id} 匹配 /owners/1 并捕获 id=1
{*path}贪婪变量捕获/resources/{*file} 匹配 /resources/a/b/c.png 并捕获 file=/a/b/c.png

媒体类型匹配

  • consumes:限制请求的 Content-Type。例如 consumes = "application/json"。支持取反表达式如 !text/plain
  • produces:限制请求的 Accept 标头。例如 produces = "application/json"

参数与标头匹配

你可以根据请求参数或 Header 的存在性、缺失或特定值来缩小映射范围:

  • params = "myParam":必须存在参数。
  • params = "!myParam":必须不存在参数。
  • params = "myParam=myValue":参数必须等于特定值。
  • headers 属性用法相同。

API 版本化 (API Versioning)

在 MVC 配置中启用后,你可以使用 version 属性:

  • 固定版本version = "1.2"
  • 基线版本version = "1.2+"(匹配 1.2 及以上)。

@HttpExchange

虽然原本是为了抽象 HTTP 客户端代码,但 @HttpExchange 也可以在服务器端作为 @RequestMapping 的替代方案。这在内部 API 开发中非常有用,可以增加客户端和服务器之间的耦合(共享接口)。


补充教学

1. 为什么“负向匹配”很有用?

在某些场景下,你可能希望一个方法处理除了某种格式外的使用请求。 例如:consumes = "!application/json"。这常用于兜底处理,确保非 JSON 请求也能获得友好的报错信息。

2. 精通通配符:** vs

  • **:主要用于路径匹配。它不关心路径的具体内容,只管“过不去”。
  • {*path}更加现代且强大。它不仅匹配余下的所有路径,还能把这一大串路径全都传给你的变量。这在构建静态资源分发系统(如私有网盘)时非常方便。

3. 理解“最佳匹配”原则

如果一个 URL 被多个模式命中,Spring 怎么选?

  1. 具体度优先:变量越少、通配符越少的越具体。
  2. 长度优先:在具体度相同的情况下,模式越长的越优先。
  3. 解析器优先PathPattern 比传统的 AntPathMatcher 更聪明,它在预解析阶段就确定了层级关系。

4. 解决 API 版本化的陷阱

在做多版本并存时,一定要注意 “最接近原则”: 如果请求版本是 1.3,而你定义了 1.2+1.5

  • Spring 会寻找小于等于 1.3 的最高版本,也就是 1.2+
  • 如果后续你新增了独立的 1.3 方法,它会完美接管 1.3 的请求。

Based on Spring Framework.