PUT vs PATCH:如何选择正确的HTTP方法优化你的API设计?

标题:深入解析HTTP方法:PUT与PATCH的关键区别及应用场景

在开发RESTful API时,PUTPATCH 是两种常用的HTTP方法,用于更新资源。尽管它们都用于更新数据,但它们在更新方式上存在显著差异。本文将通过一个员工管理系统的案例,详细探讨PUT和PATCH的工作原理、使用场景及代码实现。

1. PUT与PATCH的核心区别

  • PUT :用于完全替换 目标资源。客户端必须发送完整的资源对象,未包含的字段将被服务器设置为null或删除。

  • PATCH :用于部分更新目标资源。客户端只需发送需要更新的字段,未包含的字段将保持不变。

2. 场景分析:员工管理系统

假设我们有一个员工管理系统,员工信息包括:

  • name

  • email

  • department

场景1:使用PUT完全更新员工数据

当前员工数据:

go 复制代码
{
    "id": 1,
    "name": "Alice",
    "email": "alice@company.com",
    "department": "IT"
}

请求(PUT):

go 复制代码
PUT /employees/1
Content-Type: application/json

{
    "name": "Alice Smith",
    "email": "alice.smith@company.com"
}

响应(PUT更新后):

go 复制代码
{
    "id": 1,
    "name": "Alice Smith",
    "email": "alice.smith@company.com",
    "department": null
}

问题 :由于未发送department字段,服务器将其设置为null

场景2:使用PATCH部分更新员工数据

当前员工数据:

go 复制代码
{
    "id": 1,
    "name": "Alice",
    "email": "alice@company.com",
    "department": "IT"
}

请求(PATCH):

go 复制代码
PATCH /employees/1
Content-Type: application/json

{
    "email": "alice.smith@company.com"
}

响应(PATCH更新后):

go 复制代码
{
    "id": 1,
    "name": "Alice",
    "email": "alice.smith@company.com",
    "department": "IT"
}

优势 :仅更新了email字段,department保持不变。

3. Spring Boot代码实现

步骤1:创建员工实体类
go 复制代码
@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
    private String department;
    
    // Getters and Setters
}
步骤2:创建员工Repository
go 复制代码
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
步骤3:创建员工Controller
go 复制代码
@RestController
@RequestMapping("/employees")
public class EmployeeController {

    private final EmployeeRepository employeeRepository;

    @Autowired
    public EmployeeController(EmployeeRepository employeeRepository) {
        this.employeeRepository = employeeRepository;
    }

    // 🔹 PUT: 完全更新员工记录
    @PutMapping("/{id}")
    public ResponseEntity<Employee> updateEmployee(@PathVariable Long id, @RequestBody Employee updatedEmployee) {
        return employeeRepository.findById(id).map(existingEmployee -> {
            existingEmployee.setName(updatedEmployee.getName());
            existingEmployee.setEmail(updatedEmployee.getEmail());
            existingEmployee.setDepartment(updatedEmployee.getDepartment());
            employeeRepository.save(existingEmployee);
            return ResponseEntity.ok(existingEmployee);
        }).orElse(ResponseEntity.notFound().build());
    }

    // 🔹 PATCH: 部分更新员工记录
    @PatchMapping("/{id}")
    public ResponseEntity<Employee> partiallyUpdateEmployee(@PathVariable Long id, @RequestBody Map<String, Object> updates) {
        return employeeRepository.findById(id).map(existingEmployee -> {
            updates.forEach((key, value) -> {
                switch (key) {
                    case "name":
                        existingEmployee.setName((String) value);
                        break;
                    case "email":
                        existingEmployee.setEmail((String) value);
                        break;
                    case "department":
                        existingEmployee.setDepartment((String) value);
                        break;
                }
            });
            employeeRepository.save(existingEmployee);
            return ResponseEntity.ok(existingEmployee);
        }).orElse(ResponseEntity.notFound().build());
    }
}

4. 测试API

PUT - 完全更新

请求:

go 复制代码
PUT /employees/1
Content-Type: application/json

{
    "name": "Alice Smith",
    "email": "alice.smith@company.com"
}

响应:

go 复制代码
{
    "id": 1,
    "name": "Alice Smith",
    "email": "alice.smith@company.com",
    "department": null
}
PATCH - 部分更新

请求:

go 复制代码
PATCH /employees/1
Content-Type: application/json

{
    "email": "alice.smith@company.com"
}

响应:

go 复制代码
{
    "id": 1,
    "name": "Alice",
    "email": "alice.smith@company.com",
    "department": "IT"
}

5. 关键总结

  • PUT :适用于需要完全替换 资源的场景。未发送的字段将被设置为null

  • PATCH :适用于部分更新资源的场景。未发送的字段保持不变。

  • 实际应用 :在用户仅需更新单个字段(如email)时使用PATCH,而在需要更新所有字段时使用PUT。

通过本文的详细解析与代码示例,相信您对PUT和PATCH的区别及应用场景有了更深入的理解。如果您觉得本文有帮助,欢迎点赞支持!

相关推荐
DLYSB_3 小时前
旧上位机不肯改怎么办:原生 TCP 字节帧接入声光语音终端的改造实录
网络·网络协议·tcp/ip·报警灯
ACP广源盛139246256733 小时前
M6/M5 Pro Mac mini 端侧 AI 爆发@ACP#YLB3118 存储扩展芯片在本地 AI 服务中的机会与落地场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos
程序员夏洛3 小时前
HTTP 2.0 和 3.0 有什么区别?
网络·网络协议·http
丶浅行DE时光4 小时前
管道式电磁流量计选型指南 介质腐蚀与工况适配方案推荐
大数据·网络·人工智能·科技·推荐算法
段一凡-华北理工大学4 小时前
高炉智能布料技术与炉料分布优化~系列文章03:布料矩阵解码:环位、角度、圈数与料流的量化控制
java·网络·人工智能·矩阵·高炉智能化·高炉布料矩阵优化·高炉智能布料技术
云飞云共享云桌面7 小时前
医疗器械设备研发:多人同时操作 SolidWorks,怎样依靠单台服务器替代多工作站
运维·服务器·网络·数据库·制造
Sylvia33.7 小时前
LOL实时数据接入深度解析:从WebSocket到完整数据模型
java·网络·python·websocket·网络协议
鼹鼠SDN10 小时前
没有公网 IP,如何在外面访问家里的打印机、摄像头和整个局域网?
网络·网络协议·tcp/ip
小诗懂技术13 小时前
【网络通信UDP】基础 进程间不同主机的通信
运维·服务器·网络
DM今天肝到几点?15 小时前
AI 安全进入「攻防同频」:Gemini 3.8 Flash Cyber 上线、Astra 触及关键级、HiddenLayer 融资 1 亿美元
网络·人工智能·深度学习·安全·语言模型·开源·知识图谱