spring 引导启动器验证根本不起作用

spring boot starter validation simply not working

问题:

我需要在我的 Spring API 中验证一些 json 输入和输出,我正在尝试使用 spring 启动启动器验证(已经知道这是没有进入 spring-boot-starter-web,所以我手动添加了它)但是当基于 DTO class (MethodArgumentNotValidException)

中的验证出现问题时它永远不会抛出异常

完整的项目可以在 github

上找到

我尝试过的:

  1. 我尝试添加这 3 个依赖项:

    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.13.Final</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.el</artifactId>
        <version>3.0.0</version>
    </dependency>
    

    无法正常工作,我可以在不抛出异常的情况下发送不正确的值

    P.S。我已经知道 spring boot starter validation 没有进入 spring-boot-starter-web,所以我手动添加了它

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

    如果我尝试在没有验证的情况下使用 spring-boot-starter-validation-api(来自 javax),它直接说某些方法不存在(如 @Valid 或 @Max或@Min)

  2. 已经重建项目

  3. 已经清理 Maven 存储库并重新安装

我有:

DTO:

import lombok.*;


import javax.validation.Valid;
import javax.validation.constraints.*;
import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class StudentDTO {
    @NotEmpty(message = "Username cant be empty")
    @Size(min = 2, max = 50, message = "Minimum 2 letters, max 50")
    String studentName;
    String message;
    Double averageScore;
    List<@Valid SubjectDTO> subjects;
}
import lombok.*;

import javax.validation.constraints.*;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class SubjectDTO {
   @NotEmpty(message = "Subject name cant be empty")
   @Size(max = 30, message = "Max 30 letters")
   @Pattern(regexp = "[A-Z](\p{L}||\s)+", message = "Name should start with capital letter")
   String name;
   @Max(value = 10, message = "Max grade is 10.0")
   @Min(value = 0, message = "Min grade is 0.0")
   Double score;
}

import lombok.*;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ErrorDTO {
   private String name;
   private String description;
}

休息控制器:

import com.practicastesting.diploma.dto.StudentDTO;
import com.practicastesting.diploma.service.IObtenerDiplomaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@RestController
public class ObtenerDiplomaController {
   @Autowired
   IObtenerDiplomaService service;

   @PostMapping("/analyzeScores")
   public ResponseEntity<StudentDTO> analyzeScores(@RequestBody @Valid StudentDTO rq) {
       return new ResponseEntity<StudentDTO>(service.analyzeScores(rq), HttpStatus.OK);
   }
}

异常控制器:

import com.practicastesting.diploma.dto.ErrorDTO;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.Objects;

@ControllerAdvice
public class ExceptionController {
   @ExceptionHandler(MethodArgumentNotValidException.class)
   @ResponseBody
   @ResponseStatus(value = HttpStatus.BAD_REQUEST)
   protected ResponseEntity<ErrorDTO> handleValidationExceptions(MethodArgumentNotValidException e) {
       ErrorDTO error = new ErrorDTO("MethodArgumentNotValidException", Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
       return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
   }

}

好吧,有了这个,当我尝试发送一些 json 比如:

{
   "studentName": "a",
   "subjects": 
       [
           {
               "name": "Math",
               "score": 115
           },
           {
               "name": "Whatever",
               "score": 7
           },
           {
               "name": "Chemistry",
               "score": 6
           }
       ]
}

它应该给我一个错误,告诉我定义到 DTO 中的每个验证的消息,但没有给我任何错误或异常,它只是将它保存到存储库中,并且正常工作。

更多详情:

我正在使用:

我的 pom.xml 看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.5.4</version>
       <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>com.practicastesting</groupId>
   <artifactId>diploma</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>diploma</name>
   <description>Demo project for Spring Boot</description>
   <properties>
       <java.version>11</java.version>
   </properties>
   <dependencies>
       <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>
           <version>2.4.2</version>
       </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-devtools</artifactId>
           <scope>runtime</scope>
           <optional>true</optional>
       </dependency>
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <optional>true</optional>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>
       <dependency>
           <groupId>javax.validation</groupId>
           <artifactId>validation-api</artifactId>
           <version>2.0.1.Final</version>
       </dependency>
       <dependency>
           <groupId>org.hibernate.validator</groupId>
           <artifactId>hibernate-validator</artifactId>
           <version>6.0.13.Final</version>
       </dependency>
       <dependency>
           <groupId>org.glassfish</groupId>
           <artifactId>javax.el</artifactId>
           <version>3.0.0</version>
       </dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
               <configuration>
                   <excludes>
                       <exclude>
                           <groupId>org.projectlombok</groupId>
                           <artifactId>lombok</artifactId>
                       </exclude>
                   </excludes>
               </configuration>
           </plugin>
       </plugins>
   </build>

</project>

如果您需要更多详情,请询问,我会全部提供

你好@Sebastián Villegas,我从GitHub下载了你的项目,并用你上面添加的请求证明了它,程序正在做相应的验证(我得到的结果如下):

{
    "name": "MethodArgumentNotValidException",
    "description": "Minimum 2 letters, max 50"
}

重建您的项目。如果您使用 IntelliJ IDEA 作为 IDE,请在菜单中转到 Build -> Rebuild Project