对于最新稳定版本,请使用Spring Framework 7.0.1spring-doc.cadn.net.cn

映射请求

@RequestMapping

你可以使用@RequestMapping注释用于映射请求到控制器的方法。它已经 通过 URL、HTTP 方法、请求参数、头部和媒体匹配的各种属性 类型。你可以在类层面用它来表达共享映射,也可以在方法层面使用 以便缩小到特定的端点映射。spring-doc.cadn.net.cn

还有 HTTP 方法专用的快捷方式变体@RequestMapping:spring-doc.cadn.net.cn

这些快捷方式是自定义注释,提供的原因是, 可以说,大多数控制器方法应映射到特定的HTTP方法,而不是 用@RequestMapping,默认情况下,它与所有HTTP方法匹配。 一个@RequestMapping在类级层面仍需表达共享映射。spring-doc.cadn.net.cn

@RequestMapping不能与其他词组一起使用@RequestMapping在同一元素(类、接口或方法)上声明的注释。如果 倍数@RequestMapping在同一元素上检测到注释,警告将是 被记录,且只使用最初的映射。这同样适用于作曲@RequestMapping注释如@GetMapping,@PostMapping等。

以下示例具有类型和方法层级映射:spring-doc.cadn.net.cn

@RestController
@RequestMapping("/persons")
class PersonController {

	@GetMapping("/{id}")
	public Person getPerson(@PathVariable Long id) {
		// ...
	}

	@PostMapping
	@ResponseStatus(HttpStatus.CREATED)
	public void add(@RequestBody Person person) {
		// ...
	}
}
@RestController
@RequestMapping("/persons")
class PersonController {

	@GetMapping("/{id}")
	fun getPerson(@PathVariable id: Long): Person {
		// ...
	}

	@PostMapping
	@ResponseStatus(HttpStatus.CREATED)
	fun add(@RequestBody person: Person) {
		// ...
	}
}

URI模式

@RequestMapping方法可以通过URL模式进行映射。有两种替代方案:spring-doc.cadn.net.cn

  • 路径模式—— 一个预解析的模式,与同样预解析为 的 URL 路径匹配路径容器. 该方案专为网页应用设计,能够有效处理编码和路径参数,并高效匹配。spring-doc.cadn.net.cn

  • 蚁径匹配器——将字符串模式与字符串路径匹配。这是最初的解决方案,也用于Spring配置中用于选择类路径上的资源,文件系统及其他位置。这种方法效率较低,字符串路径输入是有效处理编码及其他URL问题的挑战。spring-doc.cadn.net.cn

路径模式是Web应用推荐的解决方案,并且是Spring WebFlux 中唯一的选择。从 5.3 版本起,它被启用用于 Spring MVC,并且默认启用。从版本 6.0 开始。请参见 MVC 配置路径匹配选项的自定义。spring-doc.cadn.net.cn

路径模式支持与 相同的模式语法蚁径匹配器. 此外,它还支持捕获模式,例如:{*Spring},用于匹配0个或多个路径段位于一条路径的末端。路径模式同时限制了用于匹配多个路径段的使用,仅允许在模式结束时使用。这消除了许多在为特定请求选择最佳匹配模式时存在的歧义。完整的模式语法请参考 PathPatternAntPathMatcher**spring-doc.cadn.net.cn

一些示例模式:spring-doc.cadn.net.cn

捕获的URI变量可以通过以下方式访问@PathVariable. 例如:spring-doc.cadn.net.cn

@GetMapping("/owners/{ownerId}/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
	// ...
}
@GetMapping("/owners/{ownerId}/pets/{petId}")
fun findPet(@PathVariable ownerId: Long, @PathVariable petId: Long): Pet {
	// ...
}

你可以在类级和方法层级声明URI变量,如下示例所示:spring-doc.cadn.net.cn

@Controller
@RequestMapping("/owners/{ownerId}")
public class OwnerController {

	@GetMapping("/pets/{petId}")
	public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
		// ...
	}
}
@Controller
@RequestMapping("/owners/{ownerId}")
class OwnerController {

	@GetMapping("/pets/{petId}")
	fun findPet(@PathVariable ownerId: Long, @PathVariable petId: Long): Pet {
		// ...
	}
}

URI 变量会自动转换为相应类型,或者类型不匹配例外被提升。简单类型 (智力,,日期,等等)默认支持,你可以注册支持任何其他数据类型。参见类型转换DataBinder.spring-doc.cadn.net.cn

你可以显式地命名URI变量(例如,@PathVariable(“customId”)),但你可以如果名称相同且你的代码编译时是用-参数编译器标志。spring-doc.cadn.net.cn

语法{varName:regex}声明一个带有正则表达式的URI变量,使得语法{varName:regex}. 例如,给定URL。“/spring-web-3.0.5.jar”,以下方法提取名称、版本和文件扩展名:spring-doc.cadn.net.cn

@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String name, @PathVariable String version, @PathVariable String ext) {
	// ...
}
@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
fun handle(@PathVariable name: String, @PathVariable version: String, @PathVariable ext: String) {
	// ...
}

URI路径模式也可以嵌入${…​}在启动时解决的占位符通过使用PropertySourcesPlaceholderConfigurer针对本地、系统、环境和其他属性源。例如,你可以利用它参数化基于某些外部配置的基础URL。spring-doc.cadn.net.cn

图案比较

当多个模式匹配一个URL时,必须选择最佳匹配。此过程包括根据是否使用解析,以下之一路径模式是否启用:spring-doc.cadn.net.cn

两者都有助于排序带有更具体特征的模式。当该模式的 URI 变量数较少(计为 1)、单万用符数(计为 1)、以及双万用符数(计为 2)较少。给定分数相等时,选择较长的模式。在相同得分和长度下,URI 变量多于万用符的模式为 选择。spring-doc.cadn.net.cn

默认映射模式()被排除在评分之外,并且总是最后排序。此外,前缀模式(例如/**/公共/**)被认为比没有双万能符的其他模式更不具备特殊性。spring-doc.cadn.net.cn

欲了解详细信息,请点击上述链接至模式比较器。spring-doc.cadn.net.cn

后缀匹配

从5.3版本开始,默认情况下Spring MVC不再执行.*后缀模式匹配控制器映射到/人也隐式映射为/人。*.因此,路径扩展不再用于解释 响应所需的内容类型——例如,/person.pdf,/person.xml, 诸如此类。spring-doc.cadn.net.cn

当浏览器发送文件时,这种方式使用文件扩展名是必要的接受头 这些内容很难一致地解读。目前,这已不再是必要, 使用接受页眉应该是首选。spring-doc.cadn.net.cn

随着时间推移,文件扩展名的使用在多种方面被证明存在问题。 当它与URI变量、路径参数和 URI编码。关于基于URL授权的推理 安全性(详见下一节)也会变得更加困难。spring-doc.cadn.net.cn

要完全禁用5.3之前版本中的路径扩展,请设置以下参数:spring-doc.cadn.net.cn

有一种方式可以请求除“接受”头部仍然可以 比如在浏览器输入URL时,会很有用。路径扩展的一个安全替代方案是 使用查询参数策略。如果必须使用文件扩展名,可以考虑限制 通过媒体类型ContentNegotiationConfigurer的财产。spring-doc.cadn.net.cn

后缀匹配与RFD

反射文件下载(RFD)攻击与XSS类似,它依赖于请求输入 (例如,查询参数和URI变量)反映在响应中。然而,代替 将JavaScript插入HTML时,RFD攻击依赖浏览器切换来执行 下载并把回复当作可执行脚本,之后双击时可以把它当作脚本处理。spring-doc.cadn.net.cn

春季MVC中,@ResponseBody响应实体方法存在风险,因为 它们可以渲染不同类型的内容,客户端可以通过 URL 路径扩展来请求这些内容。 禁用后缀模式匹配并使用路径扩展进行内容协商 降低风险,但不足以防止RFD攻击。spring-doc.cadn.net.cn

为了防止RFD攻击,在渲染响应体之前,Spring MVC会添加一个内容-倾向:inline;filename=f.txt标题建议固定且安全的下载 文件。只有当 URL 路径包含既不是也不是的文件扩展名时,才会这样做 被允许为安全,也未明确注册内容协商。不过,它确实可以 当URL直接输入浏览器时,可能会有副作用。spring-doc.cadn.net.cn

许多常见路径扩展默认被允许为安全。自定义应用HttpMessage转换器实现可以显式注册内容的文件扩展名 协商以避免发生内容-处理为这些扩展添加了标题。 参见内容类型spring-doc.cadn.net.cn

更多信息请参见CVE-2015-5211 与RFD相关的建议。spring-doc.cadn.net.cn

消耗性媒体类型

你可以根据内容类型关于请求, 如下示例所示:spring-doc.cadn.net.cn

@PostMapping(path = "/pets", consumes = "application/json") (1)
public void addPet(@RequestBody Pet pet) {
	// ...
}
1 使用消耗属性用于按内容类型缩小映射范围。
@PostMapping("/pets", consumes = ["application/json"]) (1)
fun addPet(@RequestBody pet: Pet) {
	// ...
}
1 使用消耗属性用于按内容类型缩小映射范围。

消耗属性还支持否定表达式——例如,!文本/平坦表示任意 内容类型除文本/纯文字.spring-doc.cadn.net.cn

你可以声明共享消耗属性在职业层面。与大多数其他国家不同 然而,请求映射属性在类级层面使用时,也就是方法层面消耗属性 覆盖而非扩展类级声明。spring-doc.cadn.net.cn

媒体类型为常用介质类型提供常量,例如APPLICATION_JSON_VALUEAPPLICATION_XML_VALUE.

可制作媒体类型

你可以根据接受请求头和 以下示例展示了控制器方法产生的内容类型:spring-doc.cadn.net.cn

@GetMapping(path = "/pets/{petId}", produces = "application/json") (1)
@ResponseBody
public Pet getPet(@PathVariable String petId) {
	// ...
}
1 使用生产属性用于按内容类型缩小映射范围。
@GetMapping("/pets/{petId}", produces = ["application/json"]) (1)
@ResponseBody
fun getPet(@PathVariable petId: String): Pet {
	// ...
}
1 使用生产属性用于按内容类型缩小映射范围。

媒体类型可以指定字符集。支持否定表达式——例如,!文本/平坦指除“文本/纯文字”以外的任何内容类型。spring-doc.cadn.net.cn

你可以声明共享生产属性在职业层面。与大多数其他国家不同 然而,请求映射属性在类级层面使用时,也就是方法层面生产属性 覆盖而非扩展类级声明。spring-doc.cadn.net.cn

媒体类型为常用介质类型提供常量,例如APPLICATION_JSON_VALUEAPPLICATION_XML_VALUE.

参数,头部

你可以根据请求参数条件缩小请求映射范围。你可以检测 请求参数的存在(我的param),表示没有 (!我的帕拉姆),或为 比值(myParam=myValue).以下示例展示了如何检测特定值:spring-doc.cadn.net.cn

@GetMapping(path = "/pets/{petId}", params = "myParam=myValue") (1)
public void findPet(@PathVariable String petId) {
	// ...
}
1 测试我的param等于我的价值.
@GetMapping("/pets/{petId}", params = ["myParam=myValue"]) (1)
fun findPet(@PathVariable petId: String) {
	// ...
}
1 测试我的param等于我的价值.

你也可以用同样的方法来处理请求头条件,如下示例所示:spring-doc.cadn.net.cn

@GetMapping(path = "/pets/{petId}", headers = "myHeader=myValue") (1)
public void findPet(@PathVariable String petId) {
	// ...
}
1 测试myHeader等于我的价值.
@GetMapping("/pets/{petId}", headers = ["myHeader=myValue"]) (1)
fun findPet(@PathVariable petId: String) {
	// ...
}
1 测试myHeader等于我的价值.
你们可以匹配内容类型接受使用头条条件,但更适合使用消耗生产

HTTP 头部,选项

@GetMapping(和@RequestMapping(method=HttpMethod.GET)) 支持 HTTP HEAD 透明地用于请求映射。控制器的方法无需更改。 响应装装器,应用于jakarta.servlet.http.HttpServlet,确保了内容长度头部设置为写入的字节数(但未实际写入响应)。spring-doc.cadn.net.cn

默认情况下,HTTP OPTIONS 通过设置允许HTTP列表的响应头 所有方法均列出@RequestMapping具有匹配URL模式的方法。spring-doc.cadn.net.cn

对于一个@RequestMapping如果没有HTTP方法声明,则允许首部设置为获取、头部、发布、放置、补丁、删除、选项.控制器方法应始终声明 支持的HTTP方法(例如,通过使用HTTP方法的特定变体:@GetMapping,@PostMapping,以及其他。spring-doc.cadn.net.cn

你可以显式地映射@RequestMappingHTTP HEAD 和 HTTP OPTIONS 的 method ,但 在常见情况下并非必要。spring-doc.cadn.net.cn

自定义注释

Spring MVC 支持使用组合注释进行请求映射。这些注释本身也被元注释@RequestMapping并由 组成以重新声明 的子集(或全部)@RequestMapping属性具有更狭窄、更具体的目的。spring-doc.cadn.net.cn

@GetMapping,@PostMapping,@PutMapping,@DeleteMapping@PatchMapping是 组成注释示例。他们之所以被提供,可以说是因为大多数 控制器方法应映射到特定的HTTP方法,而不是使用@RequestMapping, 默认情况下,它与所有HTTP方法匹配。如果你需要一个实现示例 写成注释,看看它们是如何声明的。spring-doc.cadn.net.cn

@RequestMapping不能与其他词组一起使用@RequestMapping在同一元素(类、接口或方法)上声明的注释。如果 倍数@RequestMapping在同一元素上检测到注释,警告将是 被记录,且只使用最初的映射。这同样适用于作曲@RequestMapping注释如@GetMapping,@PostMapping等。

Spring MVC 还支持自定义请求映射属性和自定义请求匹配 逻辑。这是一个更高级的选项,需要子职业化请求映射处理映射并且覆盖getCustomMethodCondition方法,其中 你可以检查自定义属性并返回自己的请求条件.spring-doc.cadn.net.cn

显式注册

你可以编程注册处理方法,这些方法可以用来进行动态处理 注册或高级情况,例如同一处理器的不同实例 在不同的网址下。以下示例注册了一个处理方法:spring-doc.cadn.net.cn

@Configuration
public class MyConfig {

	@Autowired
	public void setHandlerMapping(RequestMappingHandlerMapping mapping, UserHandler handler) (1)
			throws NoSuchMethodException {

		RequestMappingInfo info = RequestMappingInfo
				.paths("/user/{id}").methods(RequestMethod.GET).build(); (2)

		Method method = UserHandler.class.getMethod("getUser", Long.class); (3)

		mapping.registerMapping(info, handler, method); (4)
	}
}
1 注入目标处理器和控制器的处理器映射。
2 准备请求映射元数据。
3 学用牵引人的方法。
4 添加注册信息。
@Configuration
class MyConfig {

	@Autowired
	fun setHandlerMapping(mapping: RequestMappingHandlerMapping, handler: UserHandler) { (1)
		val info = RequestMappingInfo.paths("/user/{id}").methods(RequestMethod.GET).build() (2)
		val method = UserHandler::class.java.getMethod("getUser", Long::class.java) (3)
		mapping.registerMapping(info, handler, method) (4)
	}
}
1 注入目标处理器和控制器的处理器映射。
2 准备请求映射元数据。
3 学用牵引人的方法。
4 添加注册信息。

@HttpExchange

虽然主要目的是@HttpExchange是抽象HTTP客户端代码,其中 生成代理,是其上的HTTP 接口 此类注释是合同中立的,适用于客户端或服务器的使用。 除了简化客户端代码外,还有一些情况下 HTTP 接口 可能是服务器暴露API以便客户端访问的方便方式。这导致了 客户端与服务器之间的耦合度增加,通常不是一个好选择, 尤其是对公共 API 来说,但这可能正是内部 API 的目标。 这是春云中常用的方法,也是原因之一@HttpExchange是 作为替代方案支持的@RequestMapping用于服务器端处理 控制器类。spring-doc.cadn.net.cn

@HttpExchange("/persons")
interface PersonService {

	@GetExchange("/{id}")
	Person getPerson(@PathVariable Long id);

	@PostExchange
	void add(@RequestBody Person person);
}

@RestController
class PersonController implements PersonService {

	public Person getPerson(@PathVariable Long id) {
		// ...
	}

	@ResponseStatus(HttpStatus.CREATED)
	public void add(@RequestBody Person person) {
		// ...
	}
}
@HttpExchange("/persons")
interface PersonService {

	@GetExchange("/{id}")
	fun getPerson(@PathVariable id: Long): Person

	@PostExchange
	fun add(@RequestBody person: Person)
}

@RestController
class PersonController : PersonService {

	override fun getPerson(@PathVariable id: Long): Person {
		// ...
	}

	@ResponseStatus(HttpStatus.CREATED)
	override fun add(@RequestBody person: Person) {
		// ...
	}
}

@HttpExchange@RequestMapping有分歧。@RequestMapping可以通过路径模式、HTTP方法映射到任意数量的请求, 以及更多,同时@HttpExchange声明一个带有具体HTTP方法的单端点, 路径,以及内容类型。spring-doc.cadn.net.cn

对于方法参数和返回值,通常,@HttpExchange支撑 方法参数的子集@RequestMapping确实如此。值得注意的是,它排除了任何 服务器端特定的参数类型。详情请参见@HttpExchange@RequestMapping列表。spring-doc.cadn.net.cn