【问题标题】:Spring Bean Validation @Valid handlingSpring Bean Validation @Valid 处理
【发布时间】:2014-07-17 19:11:54
【问题描述】:

我使用 Bean Validation 1.2 创建了一个 Spring MVC REST 服务,方法如下:

@RequestMapping(value = "/valid")
public String validatedMethod(@Valid ValidObject object) {

}

如果对象无效,Tomcat 会通知我 The request sent by the client was syntactically incorrect. 和我的 validatedMethod 永远不会被调用。

如何获取在ValidObject bean 中定义的消息?我应该使用过滤器还是拦截器?

我知道我可以像下面这样重写,从注入的Validator 中获取ConstraintViolations 的集合,但上面看起来更整洁......

@RequestMapping(value = "/valid")
public String validatedMethod(ValidObject object) {
    Set<ConstraintViolation<ValidObject>> constraintViolations = validator
            .validate(object);
    if (constraintViolations.isEmpty()) {
        return "valid";
    } else {
        final StringBuilder message = new StringBuilder();
        constraintViolations.forEach((action) -> {
            message.append(action.getPropertyPath());
            message.append(": ");
            message.append(action.getMessage());
        });
        return message.toString();
    }
}

【问题讨论】:

    标签: java spring-mvc bean-validation


    【解决方案1】:

    我相信更好的方法是使用ExceptionHandler

    在您的Controller 中,您可以编写ExceptionHandler 来处理不同的异常。以下是相同的代码:

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ValidationFailureResponse validationError(MethodArgumentNotValidException ex) {
        BindingResult result = ex.getBindingResult();
        final List<FieldError> fieldErrors = result.getFieldErrors();
    
        return new ValidationFailureResponse((FieldError[])(fieldErrors.toArray(new FieldError[fieldErrors.size()])));
    }
    

    当您向控制器发送错误请求时,验证器会抛出 MethodArgumentNotValidException 类型的异常。所以理想的方法是编写一个异常处理程序来专门处理这个异常。

    在那里,您可以创建一个漂亮的响应来告诉用户出了什么问题。 我提倡这一点,因为您只需编写一次,许多Controller 方法都可以使用它。 :)

    更新

    当您对Controller 中的方法参数使用@Valid 注解时,将自动调用验证器并尝试验证对象,如果对象无效,则抛出MethodArgumentNotValidException

    如果 Spring 发现此异常的 ExceptionHandler 方法,它将执行此方法中的代码。

    您只需要确保上述方法存在于您的控制器中。

    现在还有另一种情况,当您有多个 Controllers 要验证方法参数时。在这种情况下,我建议您创建一个ExceptionResolver 类并将此方法放在那里。让你的Controllers 扩展这个类,你的工作就完成了。

    【讨论】:

    • 好的,这看起来很干。你能详细说明一下吗?如何将其连接到我的validatedMethod?哦,这个方法没有名字。
    • ValidationFailureResponse 似乎不在我的任何依赖项中,Google 认为它不存在。我可以添加哪个 Maven 依赖项?
    • 这是您的自定义响应类。我说你可以制造和发送任何你想要的响应对象:)
    • 参考您的更新:您现在可以使用@ControllerAdvice 来定义定义全局异常处理程序。
    【解决方案2】:

    试试这个

    @RequestMapping(value = "/valid")
    public String validatedMethod(@Valid ValidObject object, BindingResult result) {
        StringBuilder builder = new StringBuilder();
        List<FieldError> errors = result.getFieldErrors();
        for (FieldError error : errors ) {
           builder.append(error.getField() + " : " + error.getDefaultMessage());
        } 
        return builder.toString();
    }
    

    【讨论】:

    • 干杯,就像一个魅力 :) 不过会很好,不必为每个经过验证的方法都这样做。
    • @Dormouse 检查我的答案 :)
    【解决方案3】:

    @dharam 的答案有效。 对于 Spring v4.3 的用户,这是一个很好的实现,它使用自定义异常类来按类型处理异常。

    @RestControllerAdvice
    public class CustomExceptionClass extends ResponseEntityExceptionHandler{
       @ExceptionHandler(value = MethodArgumentNotValidException.class)
       public ResponseEntity<Object> handleException(MethodArgumentNotValidException ex, WebRequest req){
       // Build your custom response object and access the exception message using ex.getMessage()
    }
    }
    

    此方法可以统一处理所有@Controller 方法中的所有@Valid 异常

    【讨论】:

      猜你喜欢
      • 2015-05-01
      • 2022-06-29
      • 2020-04-27
      • 2015-10-17
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2012-11-26
      相关资源
      最近更新 更多