> 文档中心 > [springboot]服务端数据校验异常处理逻辑

[springboot]服务端数据校验异常处理逻辑

在这里插入图片描述

文章目录

    • 一、异常校验的规范及常用注解
    • 二、Assert断言与IllegalArgumentException
    • 三、友好的数据校验异常处理(用户输入异常的全局处理)

一、异常校验的规范及常用注解

在web开发时,对于请求参数,一般上都需要进行参数合法性校验的,原先的写法时一个个字段一个个去判断,这种方式太不通用了,所以java的JSR 303: Bean Validation规范就是解决这个问题的。
JSR 303只是个规范,并没有具体的实现,目前通常都是才有hibernate-validator进行统一参数校验。

JSR303定义的校验类型(可以参考《3.4.配置文件注入值数据校验》)

Constraint 详细信息
@Null 注释元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式
Hibernate Validator 附加的 constraint
Constraint 详细信息
-------------- --------------
@Email 被注释的元素必须是电子邮箱地址
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range 被注释的元素必须在合适的范围内

用法:把以上注解加在ArticleVO的属性字段上,然后在参数校验的方法上加@Valid注解 如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZFBNFoas-1644632559630)(images/screenshot_1597453255173.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tfNVD8J1-1644632559631)(images/screenshot_1597453285578.png)]
当用户输入参数不符合注解给出的校验规则的时候,会抛出BindException或MethodArgumentNotValidException。

二、Assert断言与IllegalArgumentException

之前给大家讲通用异常处理的时候,用户输入异常判断是这样处理的。这种方法也是可以用的,但是我们学了这么多的知识,可以优化一下。

//服务层,模拟用户输入数据导致的校验异常public void userBizError(int input)  {    if(input < 0){ //模拟业务校验失败逻辑 throw new CustomException(  CustomExceptionType.USER_INPUT_ERROR,  "您输入的数据不符合业务逻辑,请确认后重新输入!");    } //…… 其他的业务}

更好的写法是下面这样的,使用org.springframework.util.Assert断言input >= 0,如果不满足条件就抛出IllegalArgumentException,参数不合法的异常。

//服务层,模拟用户输入数据导致的校验异常public void userBizError(int input)  {    Assert.isTrue(input >= 0,"您输入的数据不符合业务逻辑,请确认后重新输入!");    //…… 其他的业务}

org.springframework.util.Assert断言提供了大量的断言方法,针对各种数据类型进行数据合法性校验,使用它我们编写代码更方便。

三、友好的数据校验异常处理(用户输入异常的全局处理)

我们已知当数据校验失败的时候,会抛出异常BindException或MethodArgumentNotValidException。所以我们对这两种异常做全局处理,防止程序员重复编码带来困扰。

@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseBodypublic AjaxResponse handleBindException(MethodArgumentNotValidException ex) {  FieldError fieldError = ex.getBindingResult().getFieldError();  return AjaxResponse.error(new CustomException(CustomExceptionType.USER_INPUT_ERROR,   fieldError.getDefaultMessage()));}@ExceptionHandler(BindException.class)@ResponseBodypublic AjaxResponse handleBindException(BindException ex) {  FieldError fieldError = ex.getBindingResult().getFieldError();  return AjaxResponse.error(new CustomException(CustomExceptionType.USER_INPUT_ERROR,   fieldError.getDefaultMessage()));}

我们已知使用org.springframework.util.Assert断言,如果不满足条件就抛出IllegalArgumentException。可以使用下面的全局异常处理函数

@ExceptionHandler(IllegalArgumentException.class)@ResponseBodypublic AjaxResponse handleIllegalArgumentException(IllegalArgumentException e) {  return AjaxResponse.error(   new CustomException(CustomExceptionType.USER_INPUT_ERROR,    e.getMessage())  );}