美文网首页
JSR303数据校验Bean Validation

JSR303数据校验Bean Validation

作者: 万事俱备就差一个程序员了 | 来源:发表于2021-09-23 19:08 被阅读0次

    后端校验技术

    JSR303技术,JSR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation,Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint,在springboot中使用也比较简便。

    1.给需要校验的字段添加校验注解

    javax.validation.constraints包下有许多的注解:

    img

    常用的校验注解补充:

    @NotBlank检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.@NotEmpty检查约束元素是否为NULL或者是EMPTY.@Length被检查的字符串长度是否在指定的范围内@CreditCardNumber信用卡验证@Email验证是否是邮件地址,如果为null,不进行验证,算通过验证。@URL验证是否是一个url地址

    注意:一个字段可以标注多个校验注解。

    2.给需要检验的方法标准@Valid

    image.png

    如果只标注了注解字段,不启用@valid的是不生效的。

    3.捕捉校验异常,返回提示信息

    对于程序可能有很多的校验注解,可能会出现多个校验错误,我们可以定义一个统一的异常处理类,帮我们捕捉校验错误并返回提示信息,这里可以利用Spring的ControllerAdvice技术。

    (1).编写统一异常处理类

    packageio.renren.app.exception;importio.renren.common.utils.R;importlombok.extern.slf4j.Slf4j;importorg.springframework.validation.BindingResult;importorg.springframework.web.bind.MethodArgumentNotValidException;importorg.springframework.web.bind.annotation.ControllerAdvice;importorg.springframework.web.bind.annotation.ExceptionHandler;importjava.util.HashMap;importjava.util.Map;/**

    * @Author zunhui

    * @Email Qiangzunhui@126.com

    * @Date 2020/8/5 13:45

    * @Description 统一异常处理

    */@RestControllerAdvice(basePackages="io.renren.app.controller")@Slf4jpublicclassAppManageControllerAdvices{@ExceptionHandler(value=MethodArgumentNotValidException.class)publicRhandleVaildException(MethodArgumentNotValidException e){log.error("数据校验出现问题{},异常类型:{}",e.getMessage(),e.getClass());BindingResult bindingResult=e.getBindingResult(); Map<String,String>errorMap=new HashMap<>();bindingResult.getFieldErrors().forEach((fieldError)->{errorMap.put(fieldError.getField(),fieldError.getDefaultMessage());});returnR.error(400,"数据校验失败").put("data",errorMap);}@ExceptionHandler(value=Throwable.class)publicRhandleException(Throwable throwable){ log.error("错误:",throwable);returnR.error(500,"系统未知异常");}}

    (2)出现异常将异常抛出

    对于校验可能会出现的异常,我们将其抛出,不予捕捉感知,都交给我们的统一异常处理类处理,返回提示信息。

    image.png

    4.分组校验(多场景的复杂校验)

    对于不同的操作,字段校验的规则和数量可能是不同的,所以我们将校验规则分组,对于不同的操作进行不同的校验组,使用groups属性。

    1.想要使用分组校验功能,根据文档我们首先编写不同的校验组接口,只编写空接口,用来表示就可以了:

    //新增分组publicinterfaceAddGroup{}//修改分组publicinterfaceUpdateGroup{}

    2.编写好分组接口,对于不同的检验规则,标注不同的分组标识:

    @NotNull(message ="修改必须指定id",groups ={UpdateGroup.class})@Null(message ="新增不能指定id",groups ={AddGroup.class})@TableIdprivate Long Id;@NotBlank(message="名称必须提交",groups={AddGroup.class,UpdateGroup.class})private String name;

    3.在controller方法上标注不同的分组校验,使用@Validated注解:

    //保存@RequestMapping("/save")//@RequiresPermissions("product:brand:save")publicRsave(@Validated({AddGroup.class})@RequestBodyBrandEntity brand){brandService.save(brand);returnR.ok();}

    @Validated({AddGroup.class}):启用不同的分组校验规则。

    注意:在使用分组校验的情况下,对于没有标注分组的校验规则,默认是不生效的,只有标注了分组的校验规则才会生效。

    5.自定义校验

    1.编写一个自定义的校验注解

    导入依赖:

    <dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId><version>2.0.1.Final</version></dependency>

    编写自定义校验注解

    packagecom.zunhui.common.valid;importjavax.validation.Constraint;importjavax.validation.Payload;importjava.lang.annotation.Documented;importjava.lang.annotation.Retention;importjava.lang.annotation.Target;importstatic java.lang.annotation.ElementType.*;importstatic java.lang.annotation.ElementType.TYPE_USE;importstatic java.lang.annotation.RetentionPolicy.RUNTIME;@Documented//指定校验器@Constraint(validatedBy={com.zunhui.common.valid.ListValueConstraintValidator.class})@Target({METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER,TYPE_USE})@Retention(RUNTIME)public@interfaceListValue{//配置默认的提示消息,新建配置文件ValidationMessages.properties在其中配置://com.zunhui.common.valid.ListValue.message = 必须提交指定的值Stringmessage()default="{com.zunhui.common.valid.ListValue.message}";Class<?>[]groups()default{}; Class<?extends Payload>[]payload()default{}; int[]vals()default{};}

    用来验证自定义的字段值,非0即1。

    2.编写一个自定义的校验器

    packagecom.zunhui.common.valid;importjavax.validation.ConstraintValidator;importjavax.validation.ConstraintValidatorContext;importjava.util.HashSet;importjava.util.Set;publicclassListValueConstraintValidatorimplementsConstraintValidator<ListValue,Integer>{privateSet<Integer>set=newHashSet<Integer>();//初始化方法publicvoidinitialize(ListValueconstraintAnnotation){int[]vals=constraintAnnotation.vals();for(intval:vals){set.add(val);}}//判断是否校验成功/**

    * @param value 需要校验的值

    * @param context

    * @return

    */publicbooleanisValid(Integervalue,ConstraintValidatorContextcontext){returnset.contains(value);}}

    3.关联自定义的校验器和自定义的校验注解

    @Constraint(validatedBy ={com.zunhui.common.valid.ListValueConstraintValidator.class})

    在自定义的校验注解中添加自己的校验器,就关联好了,一个校验注解可以指定多个不同类型的校验器,适配不同类型的校验。关联完成就可以使用了。

    4.使用

    //校验指定字段非0即1@ListValue(valus={0,1},message="提示消息,不指定则默认读取配置文件中的")privateInteger showStatus;

    测试:

    save方法传参: showStatus: 3 返回:

    image.png

    自定义校验注解生效。

    作者:稚友22

    链接:https://www.jianshu.com/p/d2ddd856cce2

    来源:简书

    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    相关文章

      网友评论

          本文标题:JSR303数据校验Bean Validation

          本文链接:https://www.haomeiwen.com/subject/zvvogltx.html