REST 控制器中的 Spring Boot 绑定和验证错误处理 [英] Spring Boot binding and validation error handling in REST controller

查看:30
本文介绍了REST 控制器中的 Spring Boot 绑定和验证错误处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我有以下带有 JSR-303(验证框架)注释的模型时:

When I have the following model with JSR-303 (validation framework) annotations:

public enum Gender {
    MALE, FEMALE
}

public class Profile {
    private Gender gender;

    @NotNull
    private String name;

    ...
}

以及以下 JSON 数据:

and the following JSON data:

{ "gender":"INVALID_INPUT" }

在我的 REST 控制器中,我想处理绑定错误(gender 属性的枚举值无效)和验证错误(name 属性不能为 null).

In my REST controller, I want to handle both the binding errors (invalid enum value for gender property) and validation errors (name property cannot be null).

以下控制器方法不起作用:

The following controller method does NOT work:

@RequestMapping(method = RequestMethod.POST)
public Profile insert(@Validated @RequestBody Profile profile, BindingResult result) {
    ...
}

这会在绑定或验证发生之前导致 com.fasterxml.jackson.databind.exc.InvalidFormatException 序列化错误.

This gives com.fasterxml.jackson.databind.exc.InvalidFormatException serialization error before binding or validation takes place.

经过一番摆弄,我想出了这个自定义代码,它可以满足我的要求:

After some fiddling, I came up with this custom code which does what I want:

@RequestMapping(method = RequestMethod.POST)
public Profile insert(@RequestBody Map values) throws BindException {

    Profile profile = new Profile();

    DataBinder binder = new DataBinder(profile);
    binder.bind(new MutablePropertyValues(values));

    // validator is instance of LocalValidatorFactoryBean class
    binder.setValidator(validator);
    binder.validate();

    // throws BindException if there are binding/validation
    // errors, exception is handled using @ControllerAdvice.
    binder.close(); 

    // No binding/validation errors, profile is populated 
    // with request values.

    ...
}

基本上,这段代码的作用是序列化为通用映射而不是模型,然后使用自定义代码绑定到模型并检查错误.

Basically what this code does, is serialize to a generic map instead of model and then use custom code to bind to model and check for errors.

我有以下问题:

  1. 自定义代码是这里的方法,还是在 Spring Boot 中有更标准的方法?
  2. @Validated 注释是如何工作的?如何制作自己的自定义注释,其作用类似于 @Validated 来封装我的自定义绑定代码?
  1. Is custom code the way to go here or is there a more standard way of doing this in Spring Boot?
  2. How does the @Validated annotation work? How can I make my own custom annotation that works like @Validated to encapsulate my custom binding code?

推荐答案

通常当 Spring MVC 无法读取 http 消息(例如请求体)时,它会抛出一个 HttpMessageNotReadableException 异常实例.因此,如果 spring 无法绑定到您的模型,它应该抛出该异常.此外,如果您在方法参数中的每个待验证模型之后NOT定义了一个 BindingResult,则在验证错误的情况下,spring 将抛出一个 MethodArgumentNotValidException 异常.有了这一切,您可以创建 ControllerAdvice 来捕获这两个异常并以您想要的方式处理它们.

Usually when Spring MVC fails to read the http messages (e.g. request body), it will throw an instance of HttpMessageNotReadableException exception. So, if spring could not bind to your model, it should throw that exception. Also, if you do NOT define a BindingResult after each to-be-validated model in your method parameters, in case of a validation error, spring will throw a MethodArgumentNotValidException exception. With all this, you can create ControllerAdvice that catches these two exceptions and handles them in your desirable way.

@ControllerAdvice(annotations = {RestController.class})
public class UncaughtExceptionsControllerAdvice {
    @ExceptionHandler({MethodArgumentNotValidException.class, HttpMessageNotReadableException.class})
    public ResponseEntity handleBindingErrors(Exception ex) {
        // do whatever you want with the exceptions
    }
}

这篇关于REST 控制器中的 Spring Boot 绑定和验证错误处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆