java - spring boot 启动器验证根本不起作用

标签 java spring-boot spring-validator

问题:

我需要在我的 Spring API 中验证一些 json 输入和输出,我正在尝试使用 spring boot starter 验证(已经知道它没有进入 spring-boot-starter-web,所以我手动添加了它)但是它根据 DTO 类 (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>
    

    并且不工作,我能够发送不正确的值而不会抛出异常

    附言已经知道spring boot starter validation没有进入spring-boot-starter-web,所以我手动添加了

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

    如果我尝试在没有 validation-api(来自 javax)的情况下使用 spring-boot-starter-validation,它会直接说某些方法不存在(如 @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;
}

休息 Controller :

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);
   }
}

异常 Controller :

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 中的每个验证的消息,但没有给我任何错误或异常,它只是将它保存到存储库中,并且正常工作。

更多详情:

我正在使用:

  • Spring 启动 2.5.4
  • Java 11

我的 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

关于java - spring boot 启动器验证根本不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69109623/

相关文章:

Java StompSession 发送消息 - Spring Boot

java - 为什么 Java 代码在移入函数时不起作用?

java - 有没有办法在 Java for-each 循环中访问迭代计数器?

java - 通过 ProcessBuilder 调用脚本和直接通过 JNI 调用 api 哪个更好?

java - Spring Validation - 用于解决字段错误的类级别验证

java - 使用哪种设计模式来避免验证类中的 if/else?

java - 使用 jQuery 插件显示 Spring 验证错误

java - 使用 IOFileFilter 的问题

java - Spring:如何使@Component线程安全?

spring-boot - 无法从 [java.lang.String] 转换为 [com.example.demo.User]