在自定义验证器 Spring Rest 中返回 HTTP 代码

Posted

技术标签:

【中文标题】在自定义验证器 Spring Rest 中返回 HTTP 代码【英文标题】:Return HTTP CODE in custom validator Spring Rest 【发布时间】:2019-01-22 16:54:26 【问题描述】:

我正在使用 Spring 开发 API REST,并且正在尝试创建一个具有 2 个验证的新自定义验证器。

对于每个验证器,我想向用户返回一个不同的 HTTP 代码,但我坚持下去,我只知道我可以在 isValid 方法中返回一个布尔值。

我希望有人可以帮助我或给我一个更好的方法来完成这件事。

UserController.java

@RestController
@RequestMapping("user")
public class UserController 
@PostMapping
public ResponseEntity<?> addUser(@Valid @RequestBody User 
     user, Errors errors)  

    //Here I don't now How to read just one error from Validator class, I just want to return 1 error using the HTTP CODE
    if (errors.hasErrors()) 
        return new ResponseEntity<>(HttpStatus.NO_CONTENT); //I'm just using a generic but I want to use the returned by Validator which has 2 validations and should return different errors
           
    return new ResponseEntity<>(user, HttpStatus.OK);
  
  

用户.java

public class User 

    @NotNull
    private final String name;

    @NotNull
    @UserConstraint
    private final Integer age;

    public User(@JsonProperty("name") String name, @JsonProperty("age") Integer age) 
        this.name = name;
        this.age = age;
    

    public String getName() 
        return name;
    

    public Integer getAge() 
        return age;
    


UserConstraint.java

@Documented
@Constraint(validatedBy = UserValidator.class)
@Target(ElementType.METHOD, ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UserConstraint 
   String message() default "Invalid age";
   Class<?>[] groups() default ;
   Class<? extends Payload>[] payload() default ;

UserValidator.java

public class UserValidator implements ConstraintValidator<UserConstraint, Integer>  

        @Override
        public void initialize(UserConstraint constraintAnnotation) 
        

        @Override
        public boolean isValid(Integer age, ConstraintValidatorContext context) 

          if(age > 60) 
              //Here I want to return HTTP CODE 402 to the user 
              return false;
           else if(age < 18) 
              //Here I want to return HTTP CODE 422 to the user 
              return false;
          
          return true;  
    

如您所见,我正在尝试对年龄进行一些验证,并且我想向用户返回不同的 HTTP 代码。

【问题讨论】:

为什么不使用标准的最小/最大年龄验证器? 我需要为每个返回不同的 HTTP CODES 和消息,此外我需要对那个方法应用更多的案例(更多的逻辑)。 我建议你可以使用ThreadLocal在UserValidator中设置验证结果,然后你可以在UserController中获取值来检查 【参考方案1】:

您可以尝试类似的方法:在 UserValidator 的 isValid 方法中抛出新的自己的异常,例如 UnderageUserException。类 UnderageException 应该扩展 RuntimeException 并且您需要使用 @ResponseStatus(value= HttpStatus.UNPROCESSABLE_ENTITY) 为 422 注释它。 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/HttpStatus.html https://www.baeldung.com/exception-handling-for-rest-with-spring 在这里你有一个很好的指南

【讨论】:

【参考方案2】:

你可以抛出一个ResponseStatusException

throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "error message");

【讨论】:

以上是关于在自定义验证器 Spring Rest 中返回 HTTP 代码的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security getAuthenticationManager() 在自定义过滤器中返回 null

Django Rest Framework:如何将数据传递给嵌套的序列化器并仅在自定义验证后创建对象

Grails spring security如何在自定义身份验证中记住我?

为啥我不能在自定义字段验证器中返回全局消息键?

Autowired 在自定义约束验证器中给出 Null 值

如何处理 grails spring-security-rest 插件中的自定义身份验证异常?