【统一全局异常处理】4. 服务端数据校验与全局异常处理

烂漫一生 提交于 2019-12-26 12:15:02

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

通常,服务端的数据校验通常不是面向用户的,提示信息还是应该以面向程序员和运维人员为主,在数据进入后台之前进行一道拦截。前端js的数据校验提示信息,是面向用户的,要更加的友好!

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

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

JSR303定义的校验类型

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注解
如:

创建Custom实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Custom {


    @NotBlank(message = "姓名不能为空!")
    String name;

    @Length(max = 11,message = "手机号长度不能超过11位!")
    String phone;

}

修改getCustom方法

    @GetMapping("/api/custom/{id}")
    public AjaxResponse getCustom(@PathVariable("id") Long id, @Valid Custom custom) {
        return AjaxResponse.success(customService.getCustom(id));
    }

测试

测试当数据校验失败的时候,会抛出异常BindException或MethodArgumentNotValidException

 

所以我们对这两种异常做全局处理,防止程序员重复编码带来困扰。

@ControllerAdvice
public class WebExceptionHandler {

    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public AjaxResponse customerException(CustomException e) {
        if (e.getCode() == CustomExceptionType.SYSTEM_ERROR.getCode()) {
            //400异常不需要持久化,将异常信息以友好的方式告知用户就可以
            //TODO 将500异常信息持久化处理,方便运维人员处理
        }
        return AjaxResponse.error(e);
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public AjaxResponse exception(Exception e) {
        //TODO 将异常信息持久化处理,方便运维人员处理

        //没有被程序员发现,并转换为CustomException的异常,都是其他异常或者未知异常.
        return AjaxResponse.error(new CustomException(CustomExceptionType.OTHER_ERROR, "未知异常"));
    }



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


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

}

重启项目测试:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!