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

Spring Controller中RequestDTO字段@NotNull验证失效求助

Spring @NotNull验证未生效的原因与解决方法

问题场景

以下是你的代码与请求情况:

Controller代码

@RestController
public class CanvasController {
    @PostMapping("/canvas/pixel")
    public void placePixel(@Valid @RequestBody final PlacePixelRequest placePixelRequest) {
        try {
            canvasManager.placePixel(placePixelRequest);
        } catch (PixelOutOfBoundsException e) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Coordinates requested are out of bounds");
        }
    }
}

请求体类

import javax.validation.constraints.NotNull;

@Data
@ToString
public class PlacePixelRequest {
    @NotNull
    private int x;
    @NotNull
    private int y;
    @NotNull
    private PixelColor pixelColor;
    @NotNull
    private String placedBy;
}

测试请求

curl --location 'http://localhost:8080/canvas/pixel' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <TOKEN>' \
--data '{
    "x": "0",
    "y": "5"
}'

依赖配置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
</dependency>

现象:即使请求体缺少pixelColor和placedBy必填字段,请求仍返回200 OK,@NotNull验证未生效。


原因分析

  1. 基本类型的@NotNull注解无效
    int是Java基本类型,默认值为0,永远不可能为null,因此@NotNull注解对基本类型字段完全不起作用,无法触发验证。

  2. 依赖冲突
    spring-boot-starter-validation已经内置了兼容版本的validation-api,手动额外引入指定版本的validation-api会导致依赖冲突,干扰Spring的验证机制正常工作。


解决方法

1. 将基本类型改为包装类

把请求体类中的int字段改为Integer包装类,包装类可以为null,@NotNull注解才能生效:

import javax.validation.constraints.NotNull;

@Data
@ToString
public class PlacePixelRequest {
    @NotNull
    private Integer x; // 替换int为Integer
    @NotNull
    private Integer y; // 替换int为Integer
    @NotNull
    private PixelColor pixelColor;
    @NotNull
    private String placedBy;
}

2. 移除多余的validation-api依赖

删除pom.xml中手动引入的javax.validation:validation-api依赖,仅保留spring-boot-starter-validation即可:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

3. 可选:添加全局异常处理器(自定义验证响应)

如果需要返回更友好的验证错误信息,可以添加全局异常处理器捕获MethodArgumentNotValidException:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationErrors(MethodArgumentNotValidException ex) {
        Map<String, String> errorMap = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach(error -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errorMap.put(fieldName, errorMessage);
        });
        return new ResponseEntity<>(errorMap, HttpStatus.BAD_REQUEST);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 02:32:32