能否在Spring控制器的@RequestMapping中设置levelId路径变量?
问题描述
我有一个遵循BREAD规范的控制器,所有操作的URL规则如下:
| 操作 | 请求方法 | 函数名 | URL |
|---|---|---|---|
| Browse(浏览) | GET | index | /api/levels/{levelId}/items |
| Read(读取) | GET | show | /api/levels/{levelId}/items/{id} |
| Edit(编辑) | PUT | update | /api/levels/{levelId}/items/{id} |
| Add(新增) | POST | create | /api/levels/{levelId}/items |
| Delete(删除) | DELETE | delete | /api/levels/{levelId}/items/{id} |
当前我的ItemController代码片段如下:
@RestController @RequestMapping("/api/levels") @RequiredArgsConstructor public class ItemController { /*...*/ @PutMapping("/{levelId}/items/{id}") public void update(@Valid @RequestBody ItemRequest request, @PathVariable Long levelId, @PathVariable Long id) { service.update(request, id, levelId); } /*...*/ }
请问是否可以将levelId路径变量移到控制器类的@RequestMapping中,改成如下写法:
@RestController @RequestMapping("/api/levels/{levelId}/items") @RequiredArgsConstructor public class ItemController { /*...*/ @PutMapping("/{id}") public void update(@Valid @RequestBody ItemRequest request, @PathVariable Long levelId, @PathVariable Long id) { service.update(request, id, levelId); } /*...*/ }
回答
完全可以这么改,这是Spring MVC中非常推荐的写法,原因如下:
路径规则完全匹配:类级别的
@RequestMapping("/api/levels/{levelId}/items")会和方法级别的@PutMapping("/{id}")自动拼接,最终生成的URL是/api/levels/{levelId}/items/{id},和你原来的Edit操作URL规则完全一致。其他操作也可以按这个逻辑调整:- Browse操作:方法上用
@GetMapping即可匹配GET /api/levels/{levelId}/items - Read操作:方法上用
@GetMapping("/{id}")匹配GET /api/levels/{levelId}/items/{id} - Add操作:方法上用
@PostMapping匹配POST /api/levels/{levelId}/items - Delete操作:方法上用
@DeleteMapping("/{id}")匹配DELETE /api/levels/{levelId}/items/{id}
- Browse操作:方法上用
代码更简洁统一:把公共路径前缀
/api/levels/{levelId}/items提到类级别,避免每个方法重复写相同的路径部分,减少冗余代码,也让控制器的职责更清晰——整个控制器都围绕/{levelId}/items这个资源展开。路径变量可正常获取:类级别定义的
{levelId}路径变量,依然可以在方法中通过@PathVariable Long levelId正常获取,Spring MVC会自动从请求URL中解析对应的值并注入到方法参数中,只要变量名称和路径占位符名称一致即可(如果名称不一致,也可以通过@PathVariable("levelId")显式指定)。
这种写法完全符合RESTful风格的资源定位原则,也让控制器结构更清晰,是值得推荐的优化方式。
内容的提问来源于stack exchange,提问作者galalem
相关产品推荐
相关产品推荐

