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

SpringBoot接收Ajax POST请求报HttpMessageNotReadableException如何解决

问题根源

  • 前后端请求格式不匹配:前端实际提交的是multipart/form-data格式的FormData数据,但强制指定了contentType: 'application/json',同时后端接口标注了consumes = "application/json",要求接收纯JSON报文。
  • Spring MVC的@RequestBody会直接读取整个请求体用Jackson做JSON反序列化,此时请求体是带multipart边界符的form-data内容,不是合法JSON,解析到开头的'-'字符时误以为是数值负号,后续没有跟数字就抛出了格式错误。

解决方案

根据是否需要上传文件可选择两种适配方案:

方案1:前端直接传纯JSON(无文件上传需求时推荐)

直接把序列化后的JSON字符串作为请求体提交,不需要用FormData包装,前端代码修改如下:

const validate = async () => {
    const l1 = {
        field1: 'l1',
        field2: 'l2'
    }
    const l2 = {
        field1: 'l3',
        field2: 'l4'
    }
    const list = [l1, l2];
    // 直接构造请求体JSON
    const dataJSON = JSON.stringify({
        field1: 'valu1',
        field2: 'valu2',
        field3: 'valu3',
        list: list
    });
    $.ajax({
        contentType: 'application/json',
        url: '/mypath/validate',
        type: 'POST',
        data: dataJSON, // 直接传JSON字符串
        async: true,
        cache: false,
        dataType: 'json',
        processData: false,
        success: function(data, textStatus, xhr) {
            //Do something
        }
    });
}

该方案不需要修改后端现有代码,@RequestBody可直接正常解析DTO,参数校验逻辑也会自动生效。

补充注意:你当前DTO使用了分组校验,如果要按指定分组校验,需要把Controller方法参数上的@Valid替换为@Validated({L1.class, L2.class, L3.class}),才能触发对应分组的校验规则。

方案2:保留FormData提交(有文件上传需求时使用)

如果需要同时上传表单文件必须使用FormData,就修改后端适配逻辑:

  1. 去掉接口的consumes = "application/json"配置,改为接收multipart/form-data请求
  2. 用@RequestParam接收JSON字符串,再手动反序列化为DTO,同时手动触发校验,代码示例:
@Controller
@SessionScope
@RequestMapping(value = "/mypath")
@Validated
public class ValidateController {
    @Autowired
    private Validator validator;

    @PostMapping(value = "/validate", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ResponseBody
    public ResponseEntity<?> validate(@RequestParam("request") String requestJson) throws JsonProcessingException {
        // 手动反序列化JSON
        ObjectMapper objectMapper = new ObjectMapper();
        RequestDTO requestDTO = objectMapper.readValue(requestJson, RequestDTO.class);
        // 手动触发参数校验
        Set<ConstraintViolation<RequestDTO>> violations = validator.validate(requestDTO);
        if (!violations.isEmpty()) {
            // 自定义处理校验异常返回
            return ResponseEntity.badRequest().body(violations.stream().map(ConstraintViolation::getMessage).toList());
        }
        return ResponseEntity.ok().body(requestDTO);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 11:21:03