You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring REST调用中x-www-form-urlencoded数组填充不一致问题

问题:x-www-form-urlencoded格式PUT请求通过-d传递数据无法绑定到Spring Boot模型属性

场景复现

你在Spring Boot应用中定义了处理JSON和form-urlencoded格式的PUT端点,其中JSON格式请求能正常接收数据,但使用curl -d传递form-urlencoded数据时,PutDataRequest对象无法被正确填充;而通过URL查询参数传递时则能成功绑定。

控制器代码

@RestController
@RequestMapping(value = "/rest/api", produces = MediaType.APPLICATION_JSON_VALUE)
public class RestApiController {

    @PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE)
    private ReturnType putRestApiTypeJson(
        @PathVariable("id") String id,
        @ModelAttribute PutDataRequest request) {
    
        System.out.println();
        return null;
        
    }

    @PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    private ReturnType putRestApiTypeUrlEncoded(
        @PathVariable("id") String id,
        @ModelAttribute PutDataRequest request) {
    
        System.out.println();
        return null;
        
    }
}

请求对象代码

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PutDataRequest {

    Set<String> characters = new HashSet<>();
    Set<String> movies = new HashSet<>();

}

测试curl命令

  • 失败案例:
curl -X PUT 'http://localhost:some-port/rest/api' -d 'characters=Some%20Name%26movies=Some%20Title' -H 'Content-Type: application/x-www-form-urlencoded'
  • 成功案例:
curl -X PUT 'http://localhost:some-port/rest/api?characters=Some%20Name%26movies=Some%20Title' -H 'Content-Type: application/x-www-form-urlencoded'

问题原因

1. 请求URL与控制器映射不匹配

控制器的PUT端点映射为/rest/api/{id},但失败案例的curl命令中缺少路径变量id,导致请求无法匹配到对应的处理方法,自然无法完成数据绑定。

2. curl参数格式错误

你在-d参数中使用%26作为键值对分隔符,但%26是&的URL编码形式。在-d参数中应直接用&分隔不同键值对,curl会自动对参数值进行URL编码。错误写法会让Spring将整个字符串解析为单个参数(键为characters,值为Some Name&movies=Some Title),无法识别movies属性。

3. Spring默认不解析PUT请求的form-urlencoded请求体

根据Servlet规范,只有POST请求的application/x-www-form-urlencoded数据会被自动解析到request.getParameter()中,PUT请求的不会。而@ModelAttribute默认从request.getParameter()中获取数据,因此即使请求体中有正确的form数据,也无法完成绑定。


解决方案

1. 修正curl命令

  • 补充路径变量id以匹配控制器映射
  • 使用&正确分隔键值对,传递集合元素时重复参数名:
# 单个元素
curl -X PUT 'http://localhost:some-port/rest/api/123' -d 'characters=Some Name&movies=Some Title' -H 'Content-Type: application/x-www-form-urlencoded'

# 多个集合元素
curl -X PUT 'http://localhost:some-port/rest/api/123' -d 'characters=Name1&characters=Name2&movies=Title1' -H 'Content-Type: application/x-www-form-urlencoded'

2. 配置Spring支持PUT请求的form数据解析

在Spring Boot的application.properties中添加配置,启用PUT请求的form数据解析:

spring.mvc.formcontent.put.enabled=true

该配置会让Spring将PUT请求体中的form数据解析到request.getParameter()中,@ModelAttribute即可正常绑定。

3. 替换@ModelAttribute为@RequestBody(可选)

如果不想依赖上述配置,可使用@RequestBody直接解析请求体中的form数据,无需额外配置:

@PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
private ReturnType putRestApiTypeUrlEncoded(
    @PathVariable("id") String id,
    @RequestBody PutDataRequest request) {

    System.out.println(request.getCharacters());
    System.out.println(request.getMovies());
    return null;
}

内容的提问来源于stack exchange,提问作者DivDiff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:31:04