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

Spring Boot应用POST请求读取失败(400错误)求助

Spring Boot POST端点400错误排查与解决

问题描述

编写了一个简单的CRUD Spring Boot应用,但POST端点/api/v1/users/4/animals无法正常工作。发送的请求体如下:

{
    "nickname": "bob",
    "kind": "cat",
    "birthday": "12.02.2020",
    "vetRecords": null
}

每次收到400错误响应:

{
    "type": "about:blank",
    "title": "Bad Request",
    "status": 400,
    "detail": "Failed to read request",
    "instance": "/api/v1/users/4/animals"
}

调试断点未触发,CommonsRequestLoggingFilter日志显示请求payload正确,但请求无法被读取。

相关代码

Controller

@PostMapping("{id}/animals")
public AnimalDto createAnimal(@PathVariable Long id,
                              @Validated(OnCreate.class) @RequestBody AnimalDto animalDto) {
    Animal animal = animalMapper.toEntity(animalDto);
    Animal createdAnimal = animalService.create(animal, id);
    return animalMapper.toDto(createdAnimal);
}

DTO

@Data
@NoArgsConstructor
@AllArgsConstructor
public class AnimalDto {
    @NotNull(message = "Id must be not null", groups = OnUpdate.class)
    private Long id;

    @NotNull(message = "Animal name must not be null", groups = {OnUpdate.class, OnCreate.class})
    @Length(max = 256, message = "Animal name must be less than 256 symbols")
    private String nickname;

    @NotNull(message = "Animal kind must not be null", groups = {OnUpdate.class, OnCreate.class})
    @Length(max = 256, message = "Animal kind must be less than 256 symbols")
    private String kind;

    @NotNull(message = "Animal age must not be null", groups = {OnUpdate.class, OnCreate.class})
    private Date birthday;

    private List<VetRecord> vetRecords;
}

Entity

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Animal {

    private Long id;
    private String nickname;
    private String kind;
    private Date birthday;
    private List<VetRecord> vetRecords;
}

Mapper(MapStruct)

@Mapper(componentModel = "spring")
public interface AnimalMapper {

    AnimalDto toDto(Animal animal);

    List<AnimalDto> toDto(List<Animal> animals);

    Animal toEntity(AnimalDto animalDto);
}

排查与解决步骤

1. 日期格式解析错误(最可能原因)

DTO中birthday为java.util.Date类型,默认Jackson解析器无法识别12.02.2020这种dd.MM.yyyy格式的字符串,导致请求体解析失败。

解决方法:

  • 给birthday字段添加格式化注解:
@NotNull(message = "Animal age must not be null", groups = {OnUpdate.class, OnCreate.class})
@JsonFormat(pattern = "dd.MM.yyyy")
private Date birthday;
  • 或者全局配置Jackson日期格式,在application.properties中添加:
spring.jackson.date-format=dd.MM.yyyy
spring.jackson.time-zone=UTC # 根据业务需求设置时区

2. 检查请求Content-Type

确保请求头的Content-Type设置为application/json,如果是表单提交或其他类型,Jackson无法解析请求体,会直接返回400错误。

3. 验证VetRecord类的可序列化性

虽然请求中vetRecords为null,但如果VetRecord类不满足Jackson序列化要求,也会导致解析失败:

  • 确保VetRecord有无参构造函数
  • 字段有对应的getter/setter(使用Lombok的@Data注解可自动生成)
  • 无循环引用或无法解析的复杂类型

4. 开启详细日志定位问题

添加Jackson和Spring MVC的调试日志,查看具体解析异常:
在application.properties中配置:

logging.level.com.fasterxml.jackson=DEBUG
logging.level.org.springframework.web.servlet.mvc.method.annotation=DEBUG

日志会输出解析过程中的具体错误信息,帮助精准定位问题。

5. 确认分组校验配置

虽然解析阶段失败会跳过校验,但需确认OnCreate和OnUpdate分组接口正确定义:

public interface OnCreate {}
public interface OnUpdate {}

确保接口为public,且Controller的@Validated注解正确引用分组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 20:47:36