乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 SpringMVC概述与DispatcherServlet

    • 本章导读:Spring MVC概述与DispatcherServlet
    • Spring MVC 是什么
    • MVC 设计模式
    • 前端控制器模式
    • DispatcherServlet
    • 核心组件协作
  • 第2章 控制器与请求映射

    • 本章导读:控制器与请求映射
    • Controller
    • RestController
    • RequestMapping
    • GetMapping
    • PostMapping
    • PutMapping
    • DeleteMapping
    • PathVariable
    • RESTful
    • 请求映射原理
  • 第3章 请求参数获取与转换

    • 本章导读:请求参数获取与转换
    • RequestParam
    • RequestBody
    • RequestHeader
    • CookieValue
    • Model
    • ModelAttribute
    • 数据绑定原理
    • 数据校验
  • 第4章 响应数据与视图解析

    • 本章导读:响应数据与视图解析
    • ResponseBody
    • ResponseEntity
    • ModelAndView
    • ViewResolver
    • HttpMessageConverter
    • forward与redirect
  • 第5章 拦截器过滤器与跨域

    • 本章导读:拦截器、过滤器与跨域
    • HandlerInterceptor
    • WebMvcConfigurer
    • CrossOrigin
    • 登录验证实战
  • 第6章 文件上传与异常处理

    • 本章导读:文件上传与异常处理
    • MultipartFile
    • 文件下载
    • ExceptionHandler
    • ControllerAdvice
    • RestControllerAdvice
    • ResponseStatus
  • 第7章 高级特性与最佳实践

    • 本章导读:高级特性与最佳实践
    • SessionAttributes
    • SessionAttribute
    • RedirectAttributes
    • MockMvc测试
    • 国际化
    • 最佳实践
  • 第8章 扩展与异步机制

    • 本章导读:扩展与异步机制
    • 异步请求处理
    • 自定义参数解析器
    • 内容协商

PutMapping

本章紧接 @PostMapping 的资源创建模式。在 RESTful 架构中,更新资源分为"全量更新"和"局部更新"两种语义。@PutMapping 对应 HTTP PUT 方法,表示全量替换资源。理解 @PutMapping,就掌握了 Spring MVC 处理资源全量更新的标准方式,以及幂等性在 API 设计中的重要意义。


定义与作用

@PutMapping 是 Spring 4.3 引入的方法级组合注解,它的职责可以用一句话概括:声明一个方法只处理 HTTP PUT 请求,用于全量更新或替换服务器上的资源。

@PutMapping 的源码定义:

@RequestMapping(method = RequestMethod.PUT)
public @interface PutMapping {
    // 继承 @RequestMapping 的所有属性
}

它与 @RequestMapping(method = RequestMethod.PUT) 完全等价。

PUT 请求的语义

在 HTTP 协议中,PUT 方法的语义是全量替换资源,具有以下特征:

  • 非安全:会改变服务器状态
  • 幂等:多次执行相同 PUT 请求,结果与执行一次相同
  • 参数在请求体中:通过请求体传递完整资源数据
  • 全量更新:请求体应包含资源的完整表示,缺失字段通常被置为 null 或默认值

核心原理

PUT 全量更新的处理流程

图解:PUT 请求的处理流程与 POST 几乎相同,但语义不同:POST 是"创建",PUT 是"全量替换"。

PUT vs POST 对比

对比维度POSTPUT
语义创建资源全量更新/替换资源
幂等性非幂等幂等
URL 指向资源集合具体资源
请求体新资源数据资源的完整新状态
缺失字段不适用(创建)通常被清空或设为默认值
HTTP 状态码201 Created200 OK 或 204 No Content

适用位置与常用属性

@PutMapping 只能标注在方法上,继承 @RequestMapping 的所有属性:

属性类型作用示例
value / pathString[]URL 路径映射"/{id}"
paramsString[]约束请求参数"force=true"
headersString[]约束请求头"X-Api-Version=2"
consumesString[]约束请求 Content-Type"application/json"
producesString[]约束响应 Content-Type"application/json"

完整示例

场景

飞翔科技的员工管理系统需要支持更新员工信息。HR 修改员工档案时,系统使用 @PutMapping 全量替换员工数据。

控制器代码

package com.feixiang.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/employees")
public class EmployeeController {

    // 容器已注入该 Bean,本教程不展开 Service 实现
    @Autowired
    private EmployeeService employeeService;

    // 全量更新员工信息
    @PutMapping("/{id}")
    public Employee update(@PathVariable Long id,
                           @RequestBody Employee employee) {
        return employeeService.update(id, employee);
    }
}

HTTP 请求示例 1:全量更新员工

curl -X PUT http://localhost:8080/employees/1001 \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "张伟",
    "department": "市场部",
    "position": "市场总监",
    "email": "zhangwei_new@feixiang.com",
    "phone": "13900139001"
  }'

实际响应(HTTP 200 OK):

{
  "id": 1001,
  "name": "张伟",
  "department": "市场部",
  "position": "市场总监",
  "email": "zhangwei_new@feixiang.com",
  "phone": "13900139001",
  "updatedAt": "2024-06-15T11:00:00"
}

分析:

  • @PutMapping("/{id}") 声明此方法只处理 PUT 请求
  • @PathVariable 提取 URL 中的 id=1001
  • @RequestBody 将请求体 JSON 反序列化为 Employee
  • Service 层执行全量替换:员工 1001 的所有字段被更新为新值
  • 注意:如果请求体中缺少某些字段(如 createdAt),全量更新可能会将其清空

HTTP 请求示例 2:幂等性验证

# 第一次 PUT
curl -X PUT http://localhost:8080/employees/1001 \
  -H "Content-Type: application/json" \
  -d '{"name":"张伟","department":"市场部","position":"市场总监"}'

# 第二次 PUT(完全相同的请求)
curl -X PUT http://localhost:8080/employees/1001 \
  -H "Content-Type: application/json" \
  -d '{"name":"张伟","department":"市场部","position":"市场总监"}'

两次响应完全相同(HTTP 200 OK):

{
  "id": 1001,
  "name": "张伟",
  "department": "市场部",
  "position": "市场总监"
}

分析:

  • 两次完全相同的 PUT 请求,服务器状态最终一致
  • 这是 PUT 的幂等性特征:无论执行多少次,资源状态与执行一次相同
  • 幂等性使得 PUT 请求可以安全地重试(网络超时后自动重发不会导致副作用)

易错场景与面试考点

误区一:用 PUT 做局部更新

错误写法:

@PutMapping("/{id}")
public Employee patch(@PathVariable Long id,
                      @RequestBody Map<String, Object> fields) {
    // 只更新传入的字段
    return employeeService.partialUpdate(id, fields);
}

纠正:PUT 的语义是全量替换,局部更新应该使用 @PatchMapping(HTTP PATCH):

// 全量更新(正确)
@PutMapping("/{id}")
public Employee update(@PathVariable Long id,
                       @RequestBody Employee employee) {
    return employeeService.update(id, employee);
}

// 局部更新(正确)
@PatchMapping("/{id}")
public Employee partialUpdate(@PathVariable Long id,
                              @RequestBody Map<String, Object> fields) {
    return employeeService.partialUpdate(id, fields);
}

误区二:PUT 请求 URL 指向集合而非具体资源

错误写法:

@PutMapping
public Employee update(@RequestBody Employee employee) {
    // URL 是 /employees,没有指定具体资源 ID
    return employeeService.update(employee);
}

纠正:PUT 的 URL 应该指向具体资源(含资源标识符),因为 PUT 是替换已有资源:

// 正确:URL 包含资源 ID
@PutMapping("/{id}")
public Employee update(@PathVariable Long id,
                       @RequestBody Employee employee) {
    return employeeService.update(id, employee);
}

面试高频:PUT 与 POST 的区别

标准回答:

  • POST 用于创建资源,PUT 用于全量更新资源
  • POST 是非幂等的(多次调用创建多个资源),PUT 是幂等的(多次调用结果相同)
  • POST 的 URL 通常指向资源集合(/employees),PUT 的 URL 指向具体资源(/employees/1001)
  • PUT 请求体应包含资源的完整表示,缺失字段可能被清空
  • PUT 可安全重试,POST 重试可能导致重复创建

小结

@PutMapping 是 Spring MVC 处理 HTTP PUT 请求的语义化注解,用于全量更新或替换资源。PUT 具有幂等性,是 RESTful API 设计中资源更新的标准方式。在实际开发中,应注意区分全量更新(PUT)和局部更新(PATCH)的语义差异。

本章与全局的关系:本章讲解了资源全量更新的映射注解。下一章"DeleteMapping"将讲解用于删除资源的 @DeleteMapping,它也是幂等的 HTTP 方法。

上一页
PostMapping
下一页
DeleteMapping