Spring Boot表单提交415错误及参数绑定异常求助
表单提交参数接收问题解决方案
问题场景
使用Thymeleaf编写HTML表单,通过@GetMapping将SomeDto对象传入页面后,表单提交时遇到以下问题:
- 用
@RequestBody接收参数时出现415 HTTP错误,提示不支持application/x-www-form-urlencoded类型 - 改用
@RequestParam接收时,DTO参数为null - 添加
consumes属性无法解决问题
相关代码
HTML表单代码
<form id="userForm" action="addObject" th:object="${objectToAdd}" method="POST"> <input th:field="*{field1}" type="text" name="a" placeholder="a" required> <input th:field="*{field2}" type="text" name="b" placeholder="b" required> <input th:field="*{field3}" type="text" name="c" placeholder="c" required> <input th:field="*{field4}" type="text" name="d" placeholder="d" required> <button type="submit">Submit</button> </form>
@GetMapping代码
@GetMapping("/form") public String getForm(Model model) { model.addAttribute("objectToAdd", new SomeDto()); return "form"; }
原@PostMapping代码
@PostMapping(value = "/form/addObject") public ResponseEntity<?> addObject(@RequestBody SomeDto someDto) { // some content }
错误信息
There was an unexpected error (type=Unsupported Media Type, status=415). Content-Type 'application/x-www-form-urlencoded;charset=UTF-8' is not supported. org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/x-www-form-urlencoded;charset=UTF-8' is not supported at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:213)
修改后的@PostMapping代码
@PostMapping(value = "/form/addObject") public ResponseEntity<?> addObject(@RequestParam(value = "someDto", required = false) ClientToAddDto clientToAddDto) { // some code }
错误原因分析
@RequestBody不兼容表单默认提交格式:@RequestBody用于接收JSON/XML格式的请求体,而浏览器默认提交表单的Content-Type是application/x-www-form-urlencoded,Spring的消息转换器无法将该格式直接转换为DTO对象,因此触发415错误。@RequestParam无法直接绑定DTO:@RequestParam用于获取单个请求参数,无法将分散的a/b/c/d参数自动封装到DTO对象中,因此得到null值。
正确解决方法
方法一:使用@ModelAttribute绑定DTO(推荐,适配普通表单提交)
这是Spring处理表单提交的标准方式,Spring会自动将请求参数绑定到DTO对象的对应字段上。
步骤1:调整HTML表单
移除手动设置的name属性,让th:field自动生成与DTO字段名一致的name(避免参数名不匹配):
<form id="userForm" action="/form/addObject" th:object="${objectToAdd}" method="POST"> <input th:field="*{field1}" type="text" placeholder="a" required> <input th:field="*{field2}" type="text" placeholder="b" required> <input th:field="*{field3}" type="text" placeholder="c" required> <input th:field="*{field4}" type="text" placeholder="d" required> <button type="submit">Submit</button> </form>
步骤2:修改@PostMapping方法
直接在参数中声明DTO对象(@ModelAttribute可省略,Spring会自动识别):
@PostMapping(value = "/form/addObject") public ResponseEntity<?> addObject(SomeDto someDto) { // 直接使用绑定后的someDto对象 return ResponseEntity.ok(someDto); }
或显式添加@ModelAttribute:
@PostMapping(value = "/form/addObject") public ResponseEntity<?> addObject(@ModelAttribute SomeDto someDto) { // some content return ResponseEntity.ok(someDto); }
方法二:AJAX提交JSON格式数据(适配前后端分离场景)
如果必须使用@RequestBody,需要通过JS将表单数据转为JSON,并设置请求头为application/json。
步骤1:修改HTML表单与提交逻辑
移除默认表单提交,改用JS处理提交:
<form id="userForm" th:object="${objectToAdd}"> <input th:field="*{field1}" type="text" placeholder="a" required> <input th:field="*{field2}" type="text" placeholder="b" required> <input th:field="*{field3}" type="text" placeholder="c" required> <input th:field="*{field4}" type="text" placeholder="d" required> <button type="button" onclick="submitForm()">Submit</button> </form> <script> function submitForm() { const form = document.getElementById('userForm'); const formData = new FormData(form); const jsonData = {}; formData.forEach((value, key) => jsonData[key] = value); fetch('/form/addObject', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify(jsonData) }) .then(res => res.json()) .then(data => console.log(data)) .catch(err => console.error('提交失败:', err)); } </script>
步骤2:保留原@PostMapping方法
无需修改,@RequestBody可正常接收JSON格式参数:
@PostMapping(value = "/form/addObject") public ResponseEntity<?> addObject(@RequestBody SomeDto someDto) { // some content return ResponseEntity.ok(someDto); }
关键注意事项
- 确保
SomeDto类存在无参构造函数,且所有需要绑定的字段都有对应的getter和setter方法,否则Spring无法完成参数绑定。 - 若DTO字段与表单参数名不一致,可使用
@RequestParam("参数名")指定映射(方法一),或@JsonProperty("参数名")指定JSON字段映射(方法二)。
内容的提问来源于stack exchange,提问作者jakub_k
相关产品推荐
相关产品推荐

