Spring Boot post请求模型验证

Vis*_*h K 0 spring-mvc spring-boot

验证发布请求 DTO bean 的推荐/最佳方法是什么?如果验证失败,我需要发送自定义错误消息,例如

{
"code": "invalid_fields",
"fields": {
    "email": "Required",
    "password": "Required",
  }
}
Run Code Online (Sandbox Code Playgroud)

DTO模型

public class SignUpRequest {

    @JsonProperty("email")
    String email;

    @JsonProperty("password")
    String password;

   public Result validate(){

   }

}
Run Code Online (Sandbox Code Playgroud)

控制器

@PostMapping(value = "/register")
public ResponseEntity<Object> signupRider(@RequestBody SignUpRequest signUpRequest) {
        Result result = signUpRequest.validate();

        return new ResponseEntity<>(x, HttpStatus.OK);
}
Run Code Online (Sandbox Code Playgroud)

SignUpRequest DTO 具有 validate 方法。 spring 进行验证的方式是什么?

谢谢。

Ale*_*rov 5

您可以使用以下技术。

  1. 在 gradle/maven 文件中添加以下依赖项

     compile "javax.validation:validation-api:2.0.1.Final"
     compile "org.hibernate.validator:hibernate-validator:6.0.9.Final"
    
    Run Code Online (Sandbox Code Playgroud)

Hibernate-validator是validation-api 2.0的实现

  1. 将 Validated 注释添加到您的控制器类

     import org.springframework.validation.annotation.Validated;
     @RestController
     @RequestMapping(value = "/contact")
     @Validated
     public class ContactController{
     }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 将有效注释添加到您的方法参数

     import org.springframework.http.HttpStatus;
     import org.springframework.http.ResponseEntity;
     import org.springframework.validation.annotation.Validated;
     import org.springframework.web.bind.annotation.PostMapping;
     import org.springframework.web.bind.annotation.RequestBody;
     import org.springframework.web.bind.annotation.RequestMapping;
     import org.springframework.web.bind.annotation.RestController;
    
     import javax.validation.Valid;
    
     @RestController
     @RequestMapping(value = "/contact")
     @Validated
     public class ContactController{
         @PostMapping(value = "/register")
         public ResponseEntity<Object> signupRider(@Valid @RequestBody SignUpRequest signUpRequest) {
         Result result = signUpRequest.validate();
    
         return new ResponseEntity<>(x, HttpStatus.OK);
        }
     }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将 Validated 注释添加到您的 dto 类

     import org.springframework.validation.annotation.Validated;
     import javax.validation.constraints.NotNull;
     import javax.validation.constraints.Email; 
    
     @Validated
     public class SignUpRequest {
    
       @JsonProperty("email")
       @Email 
       String email;
    
       @JsonProperty("password")
       @NotNull
       String password;
     }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 添加带有 RestControllerAdvice 注释的 ExceptionTranslator

     @RestControllerAdvice
     public class ExceptionTranslator {
         /**
          * Exception handler for validation errors caused by method    parameters @RequesParam, @PathVariable, @RequestHeader annotated with javax.validation constraints.
         */
         @ExceptionHandler
         protected ResponseEntity<?> handleConstraintViolationException(ConstraintViolationException exception)    {
    
             List<ApiError> apiErrors = new ArrayList<>();
    
             for (ConstraintViolation<?> violation :  exception.getConstraintViolations()) {
                 String value = (violation.getInvalidValue() == null ? null : violation.getInvalidValue().toString());
                 apiErrors.add(new  ApiError(violation.getPropertyPath().toString(), value, violation.getMessage()));
     }
    
     return ResponseEntity.badRequest().body(apiErrors);
         }
     } 
    
    Run Code Online (Sandbox Code Playgroud)
  5. 创建 ApiError 类

     import com.fasterxml.jackson.annotation.JsonIgnore;
     import lombok.AllArgsConstructor;
     import lombok.Data;
     import lombok.NoArgsConstructor;
    
     @Data
     @NoArgsConstructor
     @AllArgsConstructor
     public class ApiError {
    
       @JsonIgnore
       private int code;
       private String field;
       private String value;
       private String message;
    
       public ApiError(String message) {
         this.message = message;
       }
    
       public ApiError(String field, String value, String message) {
         this.field = field;
         this.value = value;
         this.message = message;
       }
     }
    
    Run Code Online (Sandbox Code Playgroud)

现在,如果缺少密码字段,您将看到以下响应结构:

[
  {
    "field": "password",
    "message": "must be filled"
  }
]
Run Code Online (Sandbox Code Playgroud)

如果您想使用一些自定义逻辑来验证您的字段,您可以使用以下方法

  1. 创建具体的注解类

 compile "javax.validation:validation-api:2.0.1.Final"
 compile "org.hibernate.validator:hibernate-validator:6.0.9.Final"
Run Code Online (Sandbox Code Playgroud)

  1. 创建自定义验证器

 import org.springframework.validation.annotation.Validated;
 @RestController
 @RequestMapping(value = "/contact")
 @Validated
 public class ContactController{
 }
Run Code Online (Sandbox Code Playgroud)

  1. 将 @ContactRequiredParameters 注释添加到控制器中的方法中

 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;

 import javax.validation.Valid;

 @RestController
 @RequestMapping(value = "/contact")
 @Validated
 public class ContactController{
     @PostMapping(value = "/register")
     public ResponseEntity<Object> signupRider(@Valid @RequestBody SignUpRequest signUpRequest) {
     Result result = signUpRequest.validate();

     return new ResponseEntity<>(x, HttpStatus.OK);
    }
 }
Run Code Online (Sandbox Code Playgroud)

就这样。希望能帮助到你