1. 概述
本文聚焦 Spring MVC 的核心注解之一:**@RequestMapping
**。
简单说,这个注解用于将 Web 请求映射到 Spring 控制器方法。
2. @RequestMapping
基础用法
从简单示例开始:用基础条件将 HTTP 请求映射到方法。假设 Spring 默认在根上下文路径("/")提供服务,本文所有 curl 命令都基于此。
2.1. 按路径映射
@RequestMapping(value = "/ex/foos", method = RequestMethod.GET)
@ResponseBody
public String getFoosBySimplePath() {
return "Get some Foos";
}
用 curl 测试:
curl -i http://localhost:8080/ex/foos
2.2. 按 HTTP 方法映射
HTTP 方法参数没有默认值。若不指定,会匹配所有 HTTP 请求。
下面示例映射到 POST 请求:
@RequestMapping(value = "/ex/foos", method = POST)
@ResponseBody
public String postFoos() {
return "Post some Foos";
}
用 curl 测试 POST:
curl -i -X POST http://localhost:8080/ex/foos
3. @RequestMapping
与 HTTP 请求头
3.1. 使用 headers
属性
可通过指定请求头缩小映射范围:
@RequestMapping(value = "/ex/foos", headers = "key=val", method = GET)
@ResponseBody
public String getFoosWithHeader() {
return "Get some Foos with Header";
}
用 curl 添加请求头测试:
curl -i -H "key:val" http://localhost:8080/ex/foos
支持多请求头:
@RequestMapping(
value = "/ex/foos",
headers = { "key1=val1", "key2=val2" },
method = GET)
@ResponseBody
public String getFoosWithHeaders() {
return "Get some Foos with Header";
}
测试命令:
curl -i -H "key1:val1" -H "key2:val2" http://localhost:8080/ex/foos
⚠️ 注意:curl 中用冒号分隔键值(符合 HTTP 规范),Spring 中用等号。
3.2. consumes
和 produces
属性
映射控制器方法产生的媒体类型需特别注意。
可通过 headers
属性映射 Accept
请求头:
@RequestMapping(
value = "/ex/foos",
method = GET,
headers = "Accept=application/json")
@ResponseBody
public String getFoosAsJsonFromBrowser() {
return "Get some Foos with Header Old";
}
匹配规则灵活(使用包含而非等于),以下请求仍会匹配:
curl -H "Accept:application/json,text/html" http://localhost:8080/ex/foos
Spring 3.1+ 新增 produces
和 consumes
属性:
@RequestMapping(
value = "/ex/foos",
method = RequestMethod.GET,
produces = "application/json"
)
@ResponseBody
public String getFoosAsJsonFromREST() {
return "Get some Foos with Header New";
}
测试方式相同:
curl -H "Accept:application/json" http://localhost:8080/ex/foos
produces
支持多值:
@RequestMapping(
value = "/ex/foos",
method = GET,
produces = { "application/json", "application/xml" }
)
❌ 踩坑:新旧 Accept
映射方式本质相同,不能同时使用,否则会报错:
Caused by: java.lang.IllegalStateException: Ambiguous mapping found.
Cannot map 'fooController' bean method ...
✅ 注意:produces
和 consumes
与其他注解行为不同——方法级注解会覆盖类级注解而非补充。
4. 带路径变量的 @RequestMapping
URI 部分可通过 @PathVariable
绑定到变量。
4.1. 单个路径变量
简单示例:
@RequestMapping(value = "/ex/foos/{id}", method = GET)
@ResponseBody
public String getFoosBySimplePathWithPathVariable(
@PathVariable("id") long id) {
return "Get a specific Foo with id=" + id;
}
curl 测试:
curl http://localhost:8080/ex/foos/1
若方法参数名与路径变量名一致,可简化:
@RequestMapping(value = "/ex/foos/{id}", method = GET)
@ResponseBody
public String getFoosBySimplePathWithPathVariable(
@PathVariable String id) {
return "Get a specific Foo with id=" + id;
}
@PathVariable
支持自动类型转换,可直接声明为:
@PathVariable long id
4.2. 多个路径变量
复杂 URI 需映射多个值:
@RequestMapping(value = "/ex/foos/{fooid}/bar/{barid}", method = GET)
@ResponseBody
public String getFoosBySimplePathWithPathVariables
(@PathVariable long fooid, @PathVariable long barid) {
return "Get a specific Bar with id=" + barid +
" from a Foo with id=" + fooid;
}
curl 测试:
curl http://localhost:8080/ex/foos/1/bar/2
4.3. 正则表达式路径变量
可用正则限制变量格式,例如只接受数字:
@RequestMapping(value = "/ex/bars/{numericId:[\\d]+}", method = GET)
@ResponseBody
public String getBarsBySimplePathWithPathVariable(
@PathVariable long numericId) {
return "Get a specific Bar with id=" + numericId;
}
✅ 匹配:
http://localhost:8080/ex/bars/1
❌ 不匹配:
http://localhost:8080/ex/bars/abc
5. 带请求参数的 @RequestMapping
通过 @RequestParam
轻松映射 URL 参数。
映射请求:
http://localhost:8080/ex/bars?id=100
@RequestMapping(value = "/ex/bars", method = GET)
@ResponseBody
public String getBarBySimplePathWithRequestParam(
@RequestParam("id") long id) {
return "Get a specific Bar with id=" + id;
}
curl 测试(带参数):
curl -i http://localhost:8080/ex/bars --get -d id=100
高级场景下,@RequestMapping
可显式定义参数:
@RequestMapping(value = "/ex/bars", params = "id", method = GET)
@ResponseBody
public String getBarBySimplePathWithExplicitRequestParam(
@RequestParam("id") long id) {
return "Get a specific Bar with id=" + id;
}
支持多参数(不必全部使用):
@RequestMapping(
value = "/ex/bars",
params = { "id", "second" },
method = GET)
@ResponseBody
public String getBarBySimplePathWithExplicitRequestParams(
@RequestParam("id") long id) {
return "Narrow Get a specific Bar with id=" + id;
}
以下请求会匹配最精确的映射(同时包含 id
和 second
):
http://localhost:8080/ex/bars?id=100&second=something
6. @RequestMapping
特殊场景
6.1. 多路径映射到同一方法
虽单路径映射是最佳实践,但有时需多路径映射到同一方法:
@RequestMapping(
value = { "/ex/advanced/bars", "/ex/advanced/foos" },
method = GET)
@ResponseBody
public String getFoosOrBarsByPath() {
return "Advanced - Get some Foos or Bars";
}
两个 curl 命令都会命中:
curl -i http://localhost:8080/ex/advanced/foos
curl -i http://localhost:8080/ex/advanced/bars
6.2. 多 HTTP 方法映射到同一方法
不同 HTTP 动词可映射到同一方法:
@RequestMapping(
value = "/ex/foos/multiple",
method = { RequestMethod.PUT, RequestMethod.POST }
)
@ResponseBody
public String putAndPostFoos() {
return "Advanced - PUT and POST within single method";
}
curl 测试:
curl -i -X POST http://localhost:8080/ex/foos/multiple
curl -i -X PUT http://localhost:8080/ex/foos/multiple
6.3. 全局回退映射
为特定 HTTP 方法(如 GET)实现回退:
@RequestMapping(value = "*", method = RequestMethod.GET)
@ResponseBody
public String getFallback() {
return "Fallback for GET Requests";
}
或所有请求:
@RequestMapping(
value = "*",
method = { RequestMethod.GET, RequestMethod.POST ... })
@ResponseBody
public String allFallback() {
return "Fallback for All Requests";
}
6.4. 映射冲突错误
当 Spring 发现多个相同映射时抛出此错误。相同映射指:HTTP 方法、URL、参数、请求头、媒体类型均相同。
❌ 冲突示例:
@GetMapping(value = "foos/duplicate" )
public String duplicate() {
return "Duplicate";
}
@GetMapping(value = "foos/duplicate" )
public String duplicateEx() {
return "Duplicate";
}
错误信息:
Caused by: java.lang.IllegalStateException: Ambiguous mapping.
Cannot map 'fooMappingExamplesController' method ...
✅ 解决方案:通过不同媒体类型区分:
@GetMapping(value = "foos/duplicate", produces = MediaType.APPLICATION_XML_VALUE)
public String duplicateXml() {
return "<message>Duplicate</message>";
}
@GetMapping(value = "foos/duplicate", produces = MediaType.APPLICATION_JSON_VALUE)
public String duplicateJson() {
return "{\"message\":\"Duplicate\"}";
}
其他方案:修改 URL 路径。
7. 新型请求映射快捷注解
Spring 4.3 引入基于 @RequestMapping
的快捷注解:
-
@GetMapping
-
@PostMapping
-
@PutMapping
-
@DeleteMapping
-
@PatchMapping
这些注解提升可读性,减少代码冗余。示例(CRUD API):
@GetMapping("/{id}")
public ResponseEntity<?> getBazz(@PathVariable String id){
return new ResponseEntity<>(new Bazz(id, "Bazz"+id), HttpStatus.OK);
}
@PostMapping
public ResponseEntity<?> newBazz(@RequestParam("name") String name){
return new ResponseEntity<>(new Bazz("5", name), HttpStatus.OK);
}
@PutMapping("/{id}")
public ResponseEntity<?> updateBazz(
@PathVariable String id,
@RequestParam("name") String name) {
return new ResponseEntity<>(new Bazz(id, name), HttpStatus.OK);
}
@DeleteMapping("/{id}")
public ResponseEntity<?> deleteBazz(@PathVariable String id){
return new ResponseEntity<>(new Bazz(id), HttpStatus.OK);
}
8. Spring 配置
假设 FooController
在以下包中:
package org.baeldung.spring.web.controller;
@Controller
public class FooController { ... }
只需 @Configuration
类启用 MVC 并扫描控制器:
@Configuration
@EnableWebMvc
@ComponentScan({ "org.baeldung.spring.web.controller" })
public class MvcConfig {
//
}
9. 总结
本文深入探讨了 Spring 的 @RequestMapping
注解,涵盖基础用法、HTTP 请求头映射、@PathVariable
绑定 URI 部分、@RequestParam
处理参数等核心场景。
想学习 Spring MVC 另一核心注解?可探索 @ModelAttribute
注解详解。