put 适用于全量替换且幂等的 xml 上传场景,需客户端提供完整 uri 和合法 xml;post 适用于创建新资源或非幂等操作,由服务端分配 id。两者均需严格校验 content-type、编码及 xml 结构。

PUT 上传 XML 适合资源完全替换场景
当客户端明确知道目标资源的完整 URI,且意图是「用新 XML 完全覆盖旧资源」时,PUT 是语义正确的选择。HTTP 规范要求 PUT 具有幂等性——多次相同请求效果等同于一次,这对上传失败后重试很关键。
常见错误是把 PUT 当作“任意更新”用:比如只传部分字段却用 PUT,结果意外清空未提交的字段。XML 上传尤其危险,因为解析失败或结构不匹配可能让整个资源变为空或无效。
- 必须确保客户端能构造出完整、合法的 XML,并与服务端 schema 严格对齐
- 服务端收到
PUT /api/users/123时,应直接用请求体替换 ID=123 的整条记录,不合并字段 - 响应建议返回
200 OK或204 No Content;若资源不存在且允许自动创建,可用201 Created - 注意 Nginx/Apache 默认可能禁用
PUT方法,需显式开启:limit_except GET POST PUT DELETE { allow all; }
POST 上传 XML 更适合创建或非幂等操作
POST 不要求幂等,也不预设资源已存在,因此更适合「上传 XML 创建新资源」或「触发非覆盖式处理」(如解析后生成报告、存入队列、触发工作流)。URI 通常指向集合(如 /api/orders),由服务端分配 ID 并返回 Location 头。
典型误用是用 POST 实现本该用 PUT 的全量更新,导致重复提交产生多条记录,或无法安全重试。
- 服务端需校验 XML 格式(如用
xml.etree.ElementTree或libxml2),捕获XMLSyntaxError等异常并返回400 Bad Request - Content-Type 必须为
application/xml或text/xml,否则 Spring Boot/Django/Express 可能拒绝解析 - 大 XML(>10MB)需考虑流式解析,避免内存溢出;Node.js 可用
sax,Python 推荐iterparse
Spring Boot 中如何正确接收 PUT/POST 的 XML 请求体
Spring 默认不启用 XML 绑定,需引入依赖并配置。若忽略这点,即使请求头正确,@RequestBody 也会为空或抛 HttpMessageNotReadableException。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
Controller 示例:
@PostMapping(value = "/orders", consumes = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<OrderResponse> createOrder(@RequestBody OrderXml orderXml) {
// 处理创建逻辑
}
@PutMapping(value = "/orders/{id}", consumes = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<Void> replaceOrder(@PathVariable Long id, @RequestBody OrderXml orderXml) {
// 全量替换逻辑
}
-
consumes = MediaType.APPLICATION_XML_VALUE强制校验请求头,避免 JSON 混入 - 实体类需加
@JacksonXmlRootElement和@JacksonXmlProperty注解,否则反序列化失败 - 若用 JAXB,需添加
@XmlRootElement并在application.properties中启用:spring.jackson.serialization.write-dates-as-timestamps=false
客户端上传时 Content-Type 和编码容易被忽略的细节
XML 对字符编码敏感,Content-Type 中的 charset 参数必须与 XML 声明一致,否则服务端解析会乱码或报错。例如 XML 文件首行为 <?xml version="1.0" encoding="UTF-8"?>,则请求头必须为 Content-Type: application/xml; charset=UTF-8。
curl 示例(注意 -H 和 --data-binary):
curl -X PUT http://localhost:8080/api/users/456 \ -H "Content-Type: application/xml; charset=UTF-8" \ --data-binary @user.xml
- 务必用
--data-binary而非--data,避免 curl 自动转义换行或截断空字节 - 浏览器 FormData 无法原生发 XML,需用
fetch手动设置 header 和 body 为字符串或Blob - Postman 中 Body → raw → XML(application/xml),并手动在 Headers 补全
charset - Java HttpClient 需显式设置:
request.setHeader("Content-Type", "application/xml; charset=UTF-8")










