SpringBoot+Hibernate Validator+统一异常处理

在开发过程中经常需要对一些参数进行校验比如非空判断,字符长度判断之类的,如果参数很多的话会给自己添加很多工作量,而且代码会很难看 会有很多很多的if-else 例如这样的代码

if(StringUtils.isBlank(user.getId())){
       System.out.println("id不能为空");
 }
if(StringUtils.isBlank(user.getName())){
       System.out.println("name不能为空");
 }

用Hibernate Validator可以很好的解决这个问题,简化代码量以及优化代码结构,Hibernate Validator不需要单独引入依赖,springboot的web起步依赖里面包含了,图示如下 这是项目的pom文件SpringBoot+Hibernate Validator+统一异常处理_第1张图片

大家可以看到这是起步依赖

点进去之后可以看到

SpringBoot+Hibernate Validator+统一异常处理_第2张图片

这就是我们所需要的组件,所以大家选择了web起步依赖的话就可以直接使用的

这是我的bean,可以看到我在字段上面加了注解

SpringBoot+Hibernate Validator+统一异常处理_第3张图片

NotBlank大家肯定很熟悉了,表示非空 空格也会被判定成空,这个意思是这两个字段都不允许为空,可以用来代替if-else的判断

SpringBoot+Hibernate Validator+统一异常处理_第4张图片

@Validated表示这个对象使用Validator进行校验

大家看我访问这个uri会返回什么

SpringBoot+Hibernate Validator+统一异常处理_第5张图片

大家可以看到,返回了一大串信息,对两个参数都进行了校验,接下来给大家介绍一下 BindingResult对象,这个对象里面主要是封装了上面的返回信息

SpringBoot+Hibernate Validator+统一异常处理_第6张图片大家可以看到信息已经被取出来了,可是有的同学希望在拦截到第一个参数时就返回,而不是同时返回两个被拦截的参数,我们需要加上这样一个配置

    @Bean
    public javax.validation.Validator validator(){
        ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
                .configure()
                .addProperty( "hibernate.validator.fail_fast", "true" )
                .buildValidatorFactory();
        return validatorFactory.getValidator();

    }

true为快速返回即拦截到一个参数时就返回

接下来可以看到,只打印了一个参数被拦截的message

SpringBoot+Hibernate Validator+统一异常处理_第7张图片

接下来跟大家分享一下用统一异常处理来校验

我使用@RestControllerAdvice来进行异常处理,关于@RestControllerAdvice详解可以自行去百度,很多大神已经分析得很透彻了

当接口方法去掉BindingResult时校验到不合法的参数会抛出异常,如果是用表单形式提交的参数会抛出BindException我们使用@ExceptionHandler处理即可

@RestControllerAdvice
public class ExceptionHadlers {

    //表单格式
    @ExceptionHandler(value = BindException.class)
    public Map errorHandler(BindException ex) {
        BindingResult result = ex.getBindingResult();
        StringBuilder errorMsg = new StringBuilder();
        for (ObjectError error : result.getAllErrors()) {
            errorMsg.append(error.getDefaultMessage()).append(",");
        }
        errorMsg.delete(errorMsg.length() - 1, errorMsg.length());
        Map map = new HashMap();
        map.put("code", 400);
        map.put("msg", errorMsg.toString());
        return map;
    }



}

这样每次请求的参数校验不通过的情况下都会直接返回这个map

SpringBoot+Hibernate Validator+统一异常处理_第8张图片

这个参数拦截对json格式的不生效,也就是header里面加了application/json的参数

SpringBoot+Hibernate Validator+统一异常处理_第9张图片

大家可以看到,没有进入@ExceptionHandler,但是又返回了异常信息,我代码里面并没有任何返回,说明是抛出了其它的异常,后面发现是抛出了MethodArgumentNotValidException,同理 我们再加一个@ExceptionHandler

@RestControllerAdvice
public class ExceptionHadlers {

    //json格式
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Map errorHandler(MethodArgumentNotValidException ex) {
        StringBuilder errorMsg = new StringBuilder();
        BindingResult re = ex.getBindingResult();
        for (ObjectError error : re.getAllErrors()) {
            errorMsg.append(error.getDefaultMessage()).append(",");
        }
        errorMsg.delete(errorMsg.length() - 1, errorMsg.length());
        Map map = new HashMap();
        map.put("code", 400);
        map.put("msg", errorMsg.toString());
        return map;
    }


    //表单格式
    @ExceptionHandler(value = BindException.class)
    public Map errorHandler(BindException ex) {
        BindingResult result = ex.getBindingResult();
        StringBuilder errorMsg = new StringBuilder();
        for (ObjectError error : result.getAllErrors()) {
            errorMsg.append(error.getDefaultMessage()).append(",");
        }
        errorMsg.delete(errorMsg.length() - 1, errorMsg.length());
        Map map = new HashMap();
        map.put("code", 400);
        map.put("msg", errorMsg.toString());
        return map;
    }



}

这样配置后当有校验到不合法参数时就会自动被拦截,省去许多if-else

SpringBoot+Hibernate Validator+统一异常处理_第10张图片

注意:使用统一异常处理时必须要把接口方法入参里面的BindingResult去掉,我测试时发现如果加上这个对象了就不会抛出任何异常,如果自己没有对BindingResult做逻辑处理的话,代码会继续往下走,建议如果使用BindingResult的话,可以自行处理一下逻辑。

你可能感兴趣的:(SpringBoot)