@RequestBody与@PathVariable什么时候加
@GetMapping("/page")public Result<PageResult> page(EmployeePageQueryDTO dto){log.info("员工分页查询:{}", dto);PageResult pageResult = employeeService.page(dto);return Result.success(pageResult);}
代码中EmployeePageQueryDTO dto前不用加@RequestBody吗
要不要加 @RequestBody
,只看前端用什么 HTTP 方式把参数发过来,跟代码本身无关。
- 前端把参数放在 URL 查询串(GET 请求,最常见)
SpringMVC 默认就会把查询串里的键值对 绑定到同名属性上,此时GET /employee/page?page=1&pageSize=10&name=张三
✅ 不需要@RequestBody
(你贴出的代码正是这种用法)
- 前端把参数放在 请求体(POST / PUT + application/json)
后端想一次性把整个 JSON 反序列化成 DTO,就必须POST /employee/page Content-Type: application/json{"page":1,"pageSize":10,"name":"张三"}
✅ 加@RequestBody
同时把@GetMapping
改成@PostMapping
或@RequestMapping
。
小结一句话
- 纯 GET 查询串 → 不加
- 请求体 JSON → 加,且用 POST/PUT
你的代码是 GET 方式,所以目前写法完全正确,不必加 @RequestBody
。
只要是GET方式,就不用加@RequestBody吗
对,GET 请求就没有“请求体”,所以:
-
加
@RequestBody
会报错
SpringMVC 会抛出HttpMessageNotReadableException: Required request body is missing
因为 GET 没有 body 可读。
-
不加
@RequestBody
时,Spring 只会从- URL 查询串 (
?page=1&pageSize=10
) - 或路径变量 (
/employee/{id}
)
里拿参数,再去匹配 DTO 的同名属性;找不到就填 null。
- URL 查询串 (
唯一例外(实际没人这么干)
HTTP 规范并未禁止 GET 带 body,但浏览器、网关、缓存、反向代理都会丢弃或拒绝,
因此生产环境绝对不要在 GET 里发 body,也绝对不要给 GET 方法加 @RequestBody
。
结论
只要是正经用 GET,就不用也不能加 @RequestBody
;需要 body 就用 POST/PUT 并加上 @RequestBody
。
既然GET没有请求体,那 public Result page(EmployeePageQueryDTO dto)中为什么还有(EmployeePageQueryDTO dto)参数
因为 SpringMVC 会把 URL 里的查询参数(query string)逐个拿出来,按名字匹配到 EmployeePageQueryDTO
的 字段 setter 上,完成属性绑定,根本不走“请求体”。
绑定过程(底层是 ServletRequestDataBinder)
- 收到
GET /employee/page?page=1&pageSize=10&name=Tom
- 框架发现方法签名里有个
EmployeePageQueryDTO dto
,于是- 先
new EmployeePageQueryDTO()
- 再依次执行
dto.setPage(1) dto.setPageSize(10) dto.setName("Tom")
- 先
所以
- 参数来源:URL 查询串(
?key=value
) - 绑定方式:SpringMVC 的属性绑定(@ModelAttribute 默认机制)
- 与请求体无关:GET 没有 body,DTO 也不会去 body 里找数据
一句话总结
EmployeePageQueryDTO dto
出现在 GET 方法里,只是把零散查询参数打包成一个对象,方便使用,并不依赖“请求体”。
什么时候要加@PathVariable呢
一句话规则
只要参数值出现在 URL 路径段(/
之间)而不是 ?key=value
里,就要用 @PathVariable
取。
典型例子对比
场景 | 示例 URL | 后端写法 |
---|---|---|
查询串(GET 常用) | /user?page=1&size=10 | public List<User> list(int page, int size) 或封装成 DTO 无需注解 |
路径段(RESTful) | /user/123 | @GetMapping("/user/{id}") public User detail(@PathVariable Long id) |
多段路径 | /shop/2025/05/18 | @GetMapping("/shop/{year}/{month}/{day}") public List<Order> list(@PathVariable int year, …) |
使用细节
-
名字必须对应
路径变量名{id}
与方法参数名一致时可省略 value:
@PathVariable Long id
不一致要显式写:
@PathVariable("orderId") Long id
-
支持封装到 Map
@GetMapping("/repo/**")
public void api(@PathVariable Map<String,String> map)
会把所有路径段一次性收进来。 -
一个方法可以同时出现
@PathVariable
和查询参数 /@RequestBody
@PutMapping("/user/{id}/status") public Result<Void> updateStatus(@PathVariable Long id,@RequestBody StatusDTO dto)
速记口诀
“问号后面无注解,斜杠里面加 PathVariable”