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

Spring Boot + RestController 参数验证失效问题求助

Spring Boot 3.0.5 请求验证失效问题解决

问题现状

基于Spring Boot 3.0.5的RestController项目中,请求数据验证完全不生效:无论发送不符合规则的请求数据,接口始终返回201 Created。尝试过在Controller类添加@Validated、移除方法内的try-catch块等操作,问题依旧。

现有POM依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.0.5</version>
    <relativePath/>
</parent>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
    <groupId>jakarta.validation</groupId>
    <artifactId>jakarta.validation-api</artifactId>
    <version>2.0.2</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.1.0.Final</version>
</dependency>
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>${javax.validation.version}</version>
</dependency>

Controller代码

@Slf4j @RestController
//@Validated placing this annotation here didn't helped either
public class MyController {
    @Autowired
    MyService myService;

    private final Counter requestCounter;

    public MyController(MeterRegistry meterRegistry) {
        this.requestCounter = meterRegistry.counter("my.counter");
    }

    @PostMapping("/somepath")
    public ResponseEntity<String> handle(@RequestBody @Valid InputMessage im) {
        log.debug("Received message {}",im);
        requestCounter.increment();
        try {
            myService.handleDoc(im);
            return new ResponseEntity<>("Done", HttpStatus.CREATED);
        }catch (Exception ex){
            log.error("Error with document with message id {}",im.getId(), ex);
            return new ResponseEntity<>("Failed to process request", HttpStatus.BAD_REQUEST);
        }
    }
}

InputMessage实体类

import javax.validation.constraints.*;
@Data
public class InputMessage {
    @Size(min = 1, max = 10)
    public String id;

    @NotBlank @Email
    public String email;

    @NotBlank //the same with @NotNull here
    public Integer status;

    @NotBlank
    public String error;
}

问题根源与解决方案

1. 清理依赖冲突(核心修复)

Spring Boot 3.x 基于Jakarta EE规范,你的依赖存在三大问题:混合新旧API包、重复依赖、验证器版本过低,直接导致验证功能失效。

修改POM,仅保留必要依赖:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.0.5</version>
    <relativePath/>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Spring Boot 验证启动器,自动引入适配版本的Jakarta验证API和Hibernate Validator -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <!-- 移除所有javax.validation、手动引入的jakarta.validation-api、旧版本hibernate-validator -->
</dependencies>
  • spring-boot-starter-validation已包含适配Spring Boot 3.x的验证API和实现,无需手动引入。
  • 旧的javax.validation包与Spring Boot 3.x完全不兼容,必须删除。
  • 删除重复的spring-boot-starter-validation依赖。

2. 修正实体类注解包与规则

Spring Boot 3.x 必须使用jakarta.validation.constraints包下的验证注解,同时注意注解的适用类型:

import jakarta.validation.constraints.*; // 替换javax为jakarta
@Data
public class InputMessage {
    @Size(min = 1, max = 10)
    public String id;

    @NotBlank @Email
    public String email;

    @NotNull // Integer类型不能用@NotBlank,@NotBlank仅适用于字符串
    public Integer status;

    @NotBlank
    public String error;
}
  • @NotBlank仅对字符串有效,Integer类型需用@NotNull。

3. 处理验证异常捕获

验证失败时,Spring会在进入Controller方法体之前抛出MethodArgumentNotValidException,不会走到你写的try-catch块中。可以添加全局异常处理器自定义响应:

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<String> handleValidationExceptions(MethodArgumentNotValidException ex) {
        StringBuilder sb = new StringBuilder();
        ex.getBindingResult().getAllErrors().forEach(error -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            sb.append(fieldName).append(": ").append(errorMessage).append("; ");
        });
        return new ResponseEntity<>(sb.toString(), HttpStatus.BAD_REQUEST);
    }
}

若不需要自定义响应,也可移除Controller内的try-catch块,让Spring返回默认验证错误响应。

4. 确认Controller注解正确性

@RequestBody参数上添加@Valid是正确用法,无需在Controller类上添加@Validated(除非需要路径变量等参数级验证),确保@Valid是jakarta.validation.Valid包下的注解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:15:19