BindingResult 穿越校验 合并统一异常拦截校验

发布时间:2023年12月21日

问题场景:? ? ??

?????????项目前后端对接时,前端调用服务端接口进行入参校验时,服务器和浏览器需要进行双向校验。在统一传参对象时,需要对一些入参字段进行判空,判长度,格式校验

第一种方案可以直接在对象实体的字段上使用相应注解

相关的校验API:
空检查
@NotEmpty:用在集合类上面;不能为null,而且长度必须大于0
@NotBlank: 用在String上面;只能作用在String上,不能为null,而且调用trim()后,长度必须大于0
@NotNull:用在基本类型上;不能为null,但可以为empty。

长度检查
@Size(min=,max=):验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
不要错用了异常类型,比如在int上不可用@size
@Length(min=, max=) : 只适用于String 类型

Booelan检查
@AssertTrue: 验证 Boolean 对象是否为 true
@AssertFalse: 验证 Boolean 对象是否为 false

日期检查
@Past: 验证 Date 和 Calendar 对象是否在当前时间之前
@Future: 验证 Date 和 Calendar 对象是否在当前时间之后
@Pattern: 验证 String 对象是否符合正则表达式的规则

其他验证:
@Vaild 递归验证,用于对象、数组和集合,会对对象的元素、数组的元素进行一一校验
@Email 用于验证一个字符串是否是一个合法的右键地址,空字符串或null算验证通过
@URL(protocol=,host=,port=,regexp=,flags=) 用于校验一个字符串是否是合法URL

第二种方案,如果入参比较少,也可直接取参数进行if else 判断,并对异常参数进行return 异常提示,这种直白的方式,在多代码编写时,费事费力,不推荐
第三种方案,也是比较建议的方式,在服务端接口传参处使用BindingResult

????????BindingResult是Spring框架中的一个核心接口,用于处理数据校验的结果,确保数据的合法性,BindingResult需要配合校验器Validator一起使用,在传入的对象前使用@Valid

public GraceJSONResult saveOrUpdate(@Valid SaveBO saveBO,BindingResult result) {
// 判断BindingResult是否保存错误的验证信息,如果有,则直接return
       if (result.hasErrors()) {
           Map<String, String> errorMap = getErrors(result);
           return GraceJSONResult.errorMap(errorMap);
       }
}

如果入参没有按要求传,就可以统一返回异常,如下

方案优化:
使用BindingResult可以极大省去前后端参数的校验,但像上面每个对接的服务端接口都要判断BindingResult里是否存在错误验证信息并返回,代码还是太冗余,所以进行进一步封装,将该机制放到整个服务端的统一异常拦截器里。

????????Spring提供了一个方法参数校验的异常类MethodArgumentNotValidException ,它会在所有接口接收前先进行拦截校验,如下


/**
 * 统一异常拦截处理
 * 可以针对异常的类型进行捕获,然后返回json信息到前端
 */
@ControllerAdvice
public class GraceExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public GraceJSONResult returnException(MethodArgumentNotValidException e) {
        BindingResult result = e.getBindingResult();
        Map<String, String> errors = getErrors(result);
        return GraceJSONResult.errorMap(errors);
    }

    public Map<String, String> getErrors(BindingResult result) {
        Map<String, String> map = new HashMap<>();
        List<FieldError> errorList = result.getFieldErrors();
        for (FieldError fieldError : errorList) {
            String field = fieldError.getField();
            String defaultMessage = fieldError.getDefaultMessage();
            map.put(field, defaultMessage);
        }
        return map;
    }
}

?使用统一的异常拦截后,服务端的接口参数校验就不需要每个接口都配置,依然可以实现验证效果,主打一个实现功能的前提下,能少写代码就少写,能不写就不写。

end

文章来源:https://blog.csdn.net/Zxiaobinggan/article/details/135133598
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。