PostMapping
本章紧接
@GetMapping的只读查询模式。在 RESTful 架构中,创建资源是另一个核心操作。@PostMapping是@RequestMapping(method = RequestMethod.POST)的语义化简写,它声明一个方法只处理 HTTP POST 请求,用于在服务器上创建新资源。理解@PostMapping,就掌握了 Spring MVC 处理资源创建的标准方式。
定义与作用
@PostMapping 是 Spring 4.3 引入的方法级组合注解,它的职责可以用一句话概括:声明一个方法只处理 HTTP POST 请求,用于在服务器上创建新资源。
@PostMapping 的源码定义:
@RequestMapping(method = RequestMethod.POST)
public @interface PostMapping {
// 继承 @RequestMapping 的所有属性
}
它与 @RequestMapping(method = RequestMethod.POST) 完全等价。
POST 请求的语义
在 HTTP 协议中,POST 方法的语义是提交数据、创建资源,具有以下特征:
- 非安全:会改变服务器状态(创建资源)
- 非幂等:多次执行可能创建多个资源
- 不可缓存:默认情况下 POST 响应不可缓存
- 参数在请求体中:通过请求体(body)传递数据,适合传输大量或复杂数据
核心原理
POST 请求的处理流程
图解:POST 请求通常携带请求体,@RequestBody 配合 HttpMessageConverter 将 JSON 反序列化为 Java 对象,这是创建资源的标准模式。
@GetMapping vs @PostMapping 对比
适用位置与常用属性
@PostMapping 只能标注在方法上,继承 @RequestMapping 的所有属性:
| 属性 | 类型 | 作用 | 示例 |
|---|---|---|---|
value / path | String[] | URL 路径映射 | "/employees" |
params | String[] | 约束请求参数 | "preview=true" |
headers | String[] | 约束请求头 | "X-Api-Version=2" |
consumes | String[] | 约束请求 Content-Type | "application/json" |
produces | String[] | 约束响应 Content-Type | "application/json" |
注意:@PostMapping 已经固定了 method = POST。consumes 属性在 POST 请求中非常常用,用于限制接受的请求体格式。
完整示例
场景
飞翔科技的员工管理系统需要支持创建新员工。HR 通过前端表单提交员工信息,后端使用 @PostMapping 接收并保存。
控制器代码
package com.feixiang.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/employees")
public class EmployeeController {
// 容器已注入该 Bean,本教程不展开 Service 实现
@Autowired
private EmployeeService employeeService;
// 创建新员工
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Employee create(@RequestBody Employee employee) {
return employeeService.save(employee);
}
// 批量创建员工
@PostMapping("/batch")
public List<Employee> createBatch(@RequestBody List<Employee> employees) {
return employeeService.saveAll(employees);
}
}
HTTP 请求示例 1:创建单个员工
curl -X POST http://localhost:8080/employees \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "王强",
"department": "技术部",
"position": "初级工程师",
"email": "wangqiang@feixiang.com",
"phone": "13800138003"
}'
实际响应(HTTP 201 Created):
{
"id": 1003,
"name": "王强",
"department": "技术部",
"position": "初级工程师",
"email": "wangqiang@feixiang.com",
"phone": "13800138003",
"createdAt": "2024-06-15T10:30:00"
}
分析:
@PostMapping声明此方法只处理 POST 请求@RequestBody将请求体 JSON 反序列化为Employee对象@ResponseStatus(HttpStatus.CREATED)设置响应状态码为 201(资源创建成功)- Service 保存后返回带
id和createdAt的完整对象
HTTP 请求示例 2:错误的 GET 请求
curl -X GET http://localhost:8080/employees \
-H "Accept: application/json"
实际响应(HTTP 405 Method Not Allowed):
{
"timestamp": "2024-06-15T10:35:00",
"status": 405,
"error": "Method Not Allowed",
"message": "Request method 'GET' not supported",
"path": "/employees"
}
分析:
/employees的 POST 映射和 GET 映射是独立的 HandlerMapping 条目- GET 请求命中
listAll()(如果有@GetMapping),但此处示例中如果只有@PostMapping,则返回 405 - 这体现了 RESTful 设计中"同一 URL,不同方法,不同语义"的原则
易错场景与面试考点
误区一:用 POST 做全量更新
错误写法:
@PostMapping("/{id}")
public Employee update(@PathVariable Long id,
@RequestBody Employee employee) {
return employeeService.update(id, employee);
}
纠正:全量更新应该使用 @PutMapping,POST 只用于创建。HTTP 方法的语义是 RESTful API 设计的核心:
// 正确做法
@PutMapping("/{id}")
public Employee update(@PathVariable Long id,
@RequestBody Employee employee) {
return employeeService.update(id, employee);
}
误区二:POST 请求忘记设置 Content-Type
错误请求:
curl -X POST http://localhost:8080/employees \
-d '{"name":"王强"}'
# 未设置 Content-Type,默认 application/x-www-form-urlencoded
纠正:发送 JSON 数据时必须显式设置 Content-Type: application/json,否则 Spring MVC 无法正确反序列化:
curl -X POST http://localhost:8080/employees \
-H "Content-Type: application/json" \
-d '{"name":"王强"}'
如果 Controller 标注了 consumes = "application/json",未设置 Content-Type 的请求会直接返回 415 Unsupported Media Type。
面试高频:GET 与 POST 的区别
标准回答:
- GET 用于读取资源,POST 用于创建资源
- GET 参数在 URL 中(查询字符串),POST 参数在请求体中
- GET 是安全和幂等的,POST 不是
- GET 可缓存,POST 默认不可缓存
- GET 有 URL 长度限制(约 2048 字符),POST 没有
- 敏感数据必须用 POST(避免暴露在 URL 中)
小结
@PostMapping 是 Spring MVC 处理 HTTP POST 请求的语义化注解,用于在服务器上创建新资源。它是 @RequestMapping(method = RequestMethod.POST) 的简写形式,通常与 @RequestBody 配合使用,将请求体 JSON 反序列化为 Java 对象。
本章与全局的关系:本章讲解了资源创建的映射注解。下一章"PutMapping"将讲解用于全量更新的 @PutMapping,以及 PUT 与 POST 的核心区别。