别再混淆了!一文搞懂Spring中@PatchMapping与@PutMapping的核心区别
别再混淆了一文搞懂Spring中PatchMapping与PutMapping的核心区别在构建现代Web API时HTTP方法的语义正确性往往比代码功能实现本身更能体现一个开发者的专业素养。很多刚开始接触Spring Boot或RESTful API设计的朋友对于PutMapping和PatchMapping这两个注解常常感到困惑它们不都是用来“更新”资源的吗为什么要有两个在实际项目中我见过不少因为混用它们而导致的“诡异”Bug——客户端以为只是改了个邮箱结果用户名被清空了或者一个完整的更新操作因为网络波动只提交了部分字段导致数据处于一种“半新半旧”的混乱状态。这些问题的根源往往不在于技术实现的复杂度而在于对HTTP协议底层语义和REST架构风格中“幂等性”、“安全性”等核心概念的模糊理解。本文将彻底厘清PutMapping与PatchMapping的界限。我们不止于对比注解本身的用法更会深入到HTTP/1.1协议规范RFC 7231、RESTful API设计原则并结合真实的业务场景与代码陷阱为你构建一个清晰、立体的认知框架。无论你是正在为面试准备还是希望优化现有项目的API设计理解这两者的区别都是迈向更高阶后端开发的必经之路。1. 从HTTP协议本源理解PUT与PATCH要理解Spring中的注解必须先回到它们所映射的HTTP方法本身。PUT和PATCH的定义在RFC 7231中有明确的、且截然不同的描述。PUT的核心语义是“替换”。客户端向服务器发送一个目标资源的完整表示期望服务器用这个表示完全替换掉目标资源。这里有几个关键点完整表示客户端必须提供资源在更新后应有的所有状态。如果资源有10个字段即使你只想改第10个也必须把前9个字段的当前值一并提交。幂等性这是PUT方法最重要的特性之一。无论你将同一个PUT请求执行一次、十次还是一百次在资源未被其他操作修改的前提下资源最终的状态都是完全相同的。这个特性对构建健壮的、可重试的分布式系统至关重要。创建能力如果目标资源不存在而服务器允许PUT请求可以创建一个新的资源。这通常通过检查资源ID是否存在来实现。PATCH的核心语义是“部分修改”。客户端向服务器发送一组描述资源应如何被修改的指令而不是完整的资源表示。服务器根据这些指令对目标资源进行局部更新。指令集PATCH的请求体不是资源本身而是一份“修改说明书”。这份说明书的格式需要客户端和服务器预先协商好例如JSON PatchRFC 6902或JSON Merge PatchRFC 7396。非幂等性这是PATCH与PUT最根本的区别。PATCH请求通常不是幂等的。连续执行两次“将年龄增加1岁”的PATCH操作结果是将年龄增加了2岁这与执行一次的效果不同。当然如果指令是“将年龄设置为30岁”那么它就是幂等的但PATCH方法本身不保证这一点。带宽友好当资源很大例如一个包含数十个字段的用户配置文档而只需修改其中一小部分时PATCH能显著减少网络传输的数据量。为了更直观地对比我们看下面这个表格特性维度PUT/PutMappingPATCH/PatchMapping核心语义完整替换Replace部分更新Partial Update幂等性是通常否取决于指令内容请求体内容目标资源的完整新状态描述如何修改的指令集带宽效率较低始终传输完整资源较高仅传输变更部分创建资源可以如果资源不存在通常不可以用于更新已存在资源错误恢复简单直接重试即可复杂需评估指令是否可安全重试提示幂等性Idempotent是分布式系统中的一个黄金概念。一个幂等操作意味着其执行多次所产生的影响与执行一次的影响相同。GET、PUT、DELETE都是幂等的而POST和PATCH通常不是。在设计允许客户端重试的API时这一点必须慎重考虑。2. Spring中的注解映射与典型误用场景Spring MVC包括Spring Boot的PutMapping和PatchMapping是RequestMapping(method RequestMethod.PUT/PATCH)的快捷方式。它们让HTTP方法的语义绑定变得非常直观。但正是这种直观有时会让开发者忽略其背后的契约从而产生误用。场景一用PUT实现“部分更新”这是最常见的错误。开发者设计了一个用户更新接口PUT /users/123本意是让客户端更新用户信息。但在实现时为了“方便”他允许客户端只提交想要修改的字段如只传email服务器端代码则只更新接收到的非空字段。// ❌ 错误的PUT实现它实际上执行了PATCH的职责 PutMapping(/users/{id}) public User updateUser(PathVariable Long id, RequestBody User userUpdate) { User existingUser userRepository.findById(id).orElseThrow(...); // 只更新传入的字段 if (userUpdate.getName() ! null) { existingUser.setName(userUpdate.getName()); } if (userUpdate.getEmail() ! null) { existingUser.setEmail(userUpdate.getEmail()); } // ... 其他字段类似处理 return userRepository.save(existingUser); }为什么这是错误的违反幂等性承诺假设客户端第一次调用时只传了email成功了。第二次调用可能是重试时由于某种原因email字段在序列化时被丢失了请求体变成了{}。按照上面的逻辑用户的所有字段都不会被更新。两次调用一次有email一次空产生了不同的资源状态破坏了PUT的幂等性。给客户端错误暗示客户端看到PUT会认为需要提供完整资源。如果它只提供了部分字段可能会意外地清空其他未提供的字段如果服务端实现是完整替换的话。这种不一致性会导致难以调试的Bug。场景二用PATCH实现“有条件替换”另一种误用是将PATCH当作一个“智能PUT”来用即客户端还是传递完整对象但服务端自己决定哪些字段要更新例如只更新非空字段。这比第一种情况稍好因为它没有破坏PATCH的非幂等性假设但它依然没有使用标准的PATCH指令格式导致API语义模糊。正确的做法是泾渭分明PUT用于“设置”或“覆盖”。客户端说“这是用户123的完整新数据请用它替换旧数据。”PATCH用于“修改”。客户端说“请对用户123执行以下操作将email字段替换为newexample.com。”3. 实战如何正确实现PatchMapping以JSON Patch为例要让PatchMapping真正发挥威力我们需要为它定义一种清晰的“指令语言”。JSON PatchRFC 6902是一种广泛支持的标准。一个JSON Patch文档是一个JSON数组其中的每个对象代表一个操作如add、remove、replace、move、copy、test。首先在项目中引入JSON Patch的支持。如果你使用Jackson可以添加以下依赖!-- Maven 依赖 -- dependency groupIdcom.github.java-json-tools/groupId artifactIdjson-patch/artifactId version1.13/version /dependency然后我们可以创建一个支持JSON Patch的控制器方法import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.fge.jsonpatch.JsonPatch; import com.github.fge.jsonpatch.JsonPatchException; RestController RequestMapping(/api/products) public class ProductController { Autowired private ProductService productService; Autowired private ObjectMapper objectMapper; PatchMapping(path /{id}, consumes application/json-patchjson) public ResponseEntityProduct updateProduct( PathVariable String id, RequestBody JsonNode patchDocument) { // 接收Patch指令 try { // 1. 获取现有产品实体 Product existingProduct productService.findById(id) .orElseThrow(() - new ResourceNotFoundException(Product not found)); // 2. 将实体转换为JsonNode以便应用patch JsonNode productNode objectMapper.valueToTree(existingProduct); // 3. 应用JSON Patch指令 JsonPatch patch JsonPatch.fromJson(patchDocument); JsonNode patchedNode patch.apply(productNode); // 4. 将修改后的JsonNode转换回实体 Product patchedProduct objectMapper.treeToValue(patchedNode, Product.class); // 5. 保存更新这里通常还需要验证和业务逻辑处理 Product updatedProduct productService.update(id, patchedProduct); return ResponseEntity.ok(updatedProduct); } catch (JsonPatchException e) { // 处理非法patch指令如路径不存在 return ResponseEntity.badRequest().build(); } catch (ResourceNotFoundException e) { return ResponseEntity.notFound().build(); } } }现在客户端可以发送非常精确的更新指令# 请求示例只更新产品的价格和库存 PATCH /api/products/prod-123 HTTP/1.1 Content-Type: application/json-patchjson [ { op: replace, path: /price, value: 29.99 }, { op: replace, path: /stock, value: 150 }, { op: test, path: /name, value: Old Product Name } // 确保名字未被意外修改 ]注意使用JSON Patch时test操作非常有用它可以提供一种乐观锁机制确保在应用修改前资源的某个字段符合预期值防止并发更新冲突。4. 业务场景下的选择策略与架构思考理解了技术区别后我们最终要服务于业务。如何在实际项目中做选择这里没有银弹只有权衡。优先选择PutMapping(PUT) 的场景资源较小更新频繁且多为全量更新例如一个简单的开关配置{“enabled”: true/false}。每次更新都是设置新状态用PUT简单直接。要求强一致性与简单重试机制的场景例如订单状态从“待支付”更新为“已支付”。这是一个状态机的跃迁必须是原子的、幂等的。使用PUT支付系统可以放心地重试请求而不用担心重复扣款。客户端天然拥有资源完整视图时在富客户端应用中客户端常常在内存中维护着资源的完整模型任何编辑后提交的都是新整体PUT非常合适。优先选择PatchMapping(PATCH) 的场景资源结构庞大且每次只修改极小部分最经典的例子是文档协作编辑如Google Docs。不可能每次敲一个字就PUT整个几十MB的文档。PATCH只传输增量变化效率极高。移动端等网络环境不稳定的场景为了节省用户流量和提升响应速度应尽可能只同步变更的数据。需要支持并发编辑的乐观锁结合JSON Patch的test操作可以实现更细粒度的冲突检测。客户端A和B同时编辑一个文档的不同段落他们的PATCH指令可能不会冲突从而可以自动合并这是PUT难以实现的。更新操作逻辑复杂需要原子性执行多个独立修改时一个PATCH请求可以包含多个add、remove、replace操作它们被作为一个事务执行要么全部成功要么全部失败。混合策略与API版本化在大型、演进的系统中一种常见的策略是同时提供PUT和PATCH端点。PUT用于简单的、确定性的全量替换保证向后兼容的稳定行为。PATCH用于支持更灵活、高效的增量更新但其指令格式如从JSON Merge Patch升级到JSON Patch可能在API新版本中改变。最后无论选择哪种方式API文档至关重要。你必须清晰地向客户端开发者说明对于PUT必须提供哪些字段缺失字段会被如何处理置空/忽略/报错对于PATCH支持哪种指令格式有哪些限制操作是否是原子的我在设计一个内容管理系统的API时就曾为“文章更新”接口纠结过。文章内容可能很长但用户经常只是修改一个标题或者更正一个错别字。最初我们只用PUT导致前端每次保存都要提交全文体验不佳且浪费服务器资源。后来我们引入了PATCH并采用了JSON Merge Patch格式比JSON Patch更简单但功能稍弱前端只需传{“title”: “新标题”}即可。这个改动不仅提升了性能也让API的意图表达得更清晰——从“给我一篇新文章”变成了“帮我改一下这篇文章的这个地方”。这种对细节的打磨正是专业开发的体现。

相关新闻

显卡驱动深度净化:DDU驱动清理工具系统指南——减少90%驱动故障的系统净化方案

显卡驱动深度净化:DDU驱动清理工具系统指南——减少90%驱动故障的系统净化方案

显卡驱动深度净化:DDU驱动清理工具系统指南——减少90%驱动故障的系统净化方案 【免费下载链接】display-drivers-uninstaller Display Driver Uninstaller (DDU) a driver removal utility / cleaner utility 项目地址: https://gitcode.com/gh_mirrors/di/displ…

2026/5/17 5:49:27 阅读更多 →
MedGemma X-Ray实战:从上传到获取诊断报告的完整流程

MedGemma X-Ray实战:从上传到获取诊断报告的完整流程

MedGemma X-Ray实战:从上传到获取诊断报告的完整流程 MedGemma X-Ray实战:从上传到获取诊断报告的完整流程 —— 无需医学背景也能上手的AI影像解读工具。它不替代医生,但能帮你快速理解一张胸部X光片在说什么:胸廓是否对称&#…

2026/7/4 13:15:45 阅读更多 →
⚖️Lychee-Rerank部署案例:中小企业私有化检索增强(RAG)落地实践

⚖️Lychee-Rerank部署案例:中小企业私有化检索增强(RAG)落地实践

Lychee-Rerank部署案例:中小企业私有化检索增强(RAG)落地实践 1. 项目简介 Lychee-Rerank是一个专门为中小企业设计的本地化检索相关性评分工具。它基于Qwen2.5-1.5B模型开发,完全在本地运行,不需要联网,…

2026/5/17 5:49:26 阅读更多 →

最新新闻

AI工具链选型:GitHub Copilot与Cursor、Codeium企业开发场景实测对比

AI工具链选型:GitHub Copilot与Cursor、Codeium企业开发场景实测对比

AI工具链选型:GitHub Copilot与Cursor、Codeium企业开发场景实测对比 一、评测体系设计与方法论 AI编码助手已成为开发效率的关键杠杆。本次评测聚焦三项主流工具的实际表现。从四个维度建立可复现的量化评测框架。 %%{init: {theme: base}}%% radartitle AI编码助手…

2026/7/5 1:20:14 阅读更多 →
PyTorch 数据加载瓶颈:GPU 空等时先看 DataLoader

PyTorch 数据加载瓶颈:GPU 空等时先看 DataLoader

PyTorch 数据加载瓶颈:GPU 空等时先看 DataLoader 一、训练慢不一定是模型慢 PyTorch 训练时,很多人看到速度慢就先改模型、调 batch size、换显卡。但如果 GPU 利用率忽高忽低,可能瓶颈根本不在模型,而在数据加载。图片解码、文本…

2026/7/5 1:20:14 阅读更多 →
群晖DSM 7.2.2视频管理终极解决方案:免费恢复Video Station完整功能

群晖DSM 7.2.2视频管理终极解决方案:免费恢复Video Station完整功能

群晖DSM 7.2.2视频管理终极解决方案:免费恢复Video Station完整功能 【免费下载链接】Video_Station_for_DSM_722 Script to install Video Station in DSM 7.2.2 and DSM 7.3 项目地址: https://gitcode.com/gh_mirrors/vi/Video_Station_for_DSM_722 你是否…

2026/7/5 1:20:14 阅读更多 →
云原生可观测性:构建全链路监控体系

云原生可观测性:构建全链路监控体系

引言在微服务架构和容器化部署成为主流的当下,系统的复杂性呈指数级增长。一个请求可能跨越数十个服务实例,传统的日志查看和单点监控已无法满足故障排查的需求。云原生可观测性(Observability)应运而生,它通过Metrics…

2026/7/5 1:18:13 阅读更多 →
工训赛智能小车 PCB 自制指南:从 BTN7971B 四路驱动到主控布局的 5 个要点

工训赛智能小车 PCB 自制指南:从 BTN7971B 四路驱动到主控布局的 5 个要点

工训赛智能小车PCB设计实战:从四路驱动到主控布局的进阶指南在工程训练综合能力竞赛的智能物流搬运赛项中,一辆性能卓越的小车往往始于精良的PCB设计。当现成模块难以满足定制化需求时,自主设计PCB不仅能显著降低成本,更能实现整车…

2026/7/5 1:18:13 阅读更多 →
FastAPI零基础教程(八)- 后台任务、WebSocket与高级特性,半天吃透进阶能力

FastAPI零基础教程(八)- 后台任务、WebSocket与高级特性,半天吃透进阶能力

文章目录前言一、阶段学习目标(半天速成)二、核心一:BackgroundTasks 后台任务(解耦耗时操作)2\.1 核心原理2\.2 基础实战:简单后台任务2\.3 多任务叠加 \ 异步任务支持2\.4 关键避坑点(生产必看…

2026/7/5 1:18:13 阅读更多 →

日新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻