Spring中@RequestBody空JSON或空请求体导致校验未触发,需从校验入口配置(如引入spring-boot-starter-validation、正确使用@Valid、DTO含无参构造)和非法请求体拦截(自定义空值检查、全局捕获HttpMessageNotReadableException)两层解决。

当 @RequestBody 接收空 JSON(如 {})、null 字段、或整个请求体为空(如前端发了个空字符串 "" 或未设置 Content-Type)时,Spring 默认不会触发字段级校验,甚至可能直接抛出 HttpMessageNotReadableException 或 NullPointerException。这不是校验“失败”,而是校验根本没启动。真正的兜底,得从**校验入口是否被触发**和**空/非法请求体如何拦截**两层入手。
确保校验器能真正运行起来
很多问题其实卡在第一步:@Valid 没生效。
- 必须引入 spring-boot-starter-validation 依赖,仅靠 spring-boot-starter-web 不够;
- @Valid 只能加在 @RequestBody 参数前,不能加在类上或方法上(那是 @Validated 的用法);
- DTO 必须有无参构造函数,否则 Jackson 反序列化失败,校验根本不会执行;
- 避免用 Map<String, Object> 接收,它绕过所有 Bean 校验逻辑,只能手写 if 判断。
拦截空 JSON 或非法请求体
空对象 {} 本身是合法 JSON,但字段全为 null,此时字段级注解(如 @NotBlank)不报错——因为它们只校验“有值但不合规则”。要捕获这种“结构存在但语义为空”的情况,需主动干预:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 在 DTO 中添加一个自定义校验方法,用
@AssertTrue或@ScriptAssert检查关键字段是否全空; - 更常用的是在 Controller 方法里,校验反序列化后的对象是否“实质为空”:
if (requestVo == null || StringUtils.isBlank(requestVo.getId()) && StringUtils.isBlank(requestVo.getName())) {
return Result.fail("请求参数不能为空");
} - 对空请求体(如发送了
Content-Type: application/json但 body 是空字符串),Spring 默认会抛HttpMessageNotReadableException,需全局异常处理器统一捕获并返回友好提示。
全局异常统一兜底处理
把校验失败、空体、类型转换异常等都归到一个地方响应,避免堆栈暴露给前端:
- 用
@ControllerAdvice+@ExceptionHandler(MethodArgumentNotValidException.class)处理字段校验失败; - 加一个
@ExceptionHandler(HttpMessageNotReadableException.class)捕获空体、非法 JSON、类型不匹配等; - 再加一个
@ExceptionHandler(Exception.class)做最外层兜底(慎用,建议限定包路径); - 每种异常都返回标准格式的错误码和提示,比如:
{"code":400,"msg":"请求数据格式错误,请检查JSON结构"}
前端配合降低后端压力
兜底是保底手段,不是替代规范:
- 约定接口文档明确要求必传字段,前端发请求前做基础非空判断;
- 开发环境开启 Swagger,利用
@ApiModel+@ApiModelProperty(required = true)提示必填项; - 对敏感操作(如支付、删除),后端可额外加一层业务级空校验,不依赖字段注解。

















