基于注解的参数校验器 Hibernate Validator
前言
你还在为校验入参时写的那一串 if...else... 而苦恼嘛?
你还在为了编写一个功能全面的参数校验器而夜夜不寐嘛
人生苦短,大可不必讲宝贵的编程时间耗费在这些事情上~
是时候换个活法啦!有现成的工具,拿去用吧!
看看上面这种参数校验,多么的 优雅~
直接通过在属性上写注解就可以达到给参数增加校验规则的目的啦!
基于注解的参数校验器
JSR303
JSR303是一套JavaBean参数校验的 标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面,就可以在需要校验的时候进行校验了。
ps. 没有列举全,感兴趣的可以看JSR303官方文档。
Hibernate Validator
Hibernate Validator在JSR303的基础上对校验注解进行了扩展
ps. 同样没列举全,大家感兴趣可以看Hibernate Validator官方文档。
Hibernate Validator就决定是你了
基本上Hibernate validator就包括了所有常用的校验规则,而且它又是在JSR303基础上的扩展,所以直接 推荐使用 Hibernate Validator了。
Hibernate Validator版本
可以看到Hibernate validator目前有两个稳定的版本,各取所需。
这篇文章里面的例子用到的版本是 5.4.2.Final
。
Maven引用
代码实现
对Object的属性进行校验
如上,给 User
这个Bean的三个属性增加了相应的规则,message
后面规定的是校验不通过时报的错误信息文案:
用户名name字段不能为null,也不能为空字符串(会过滤空格)。
用户erp字段不能为null,也不能为空字符串(会过滤空格),且字符串长度不能小于3。
用户年龄age字段不能小于22。
如上,在Controller的接口参数(刚定义的Bean)之前添加 @Valid
注解。
这样就可以用啦,校验不通过的时候会抛出异常,具体怎么处理异常就根据自己的项目需要来吧。
分组校验
有的时候,在不同场景下我们需要对同一个Bean里面的不同参数进行校验。
比如说,在新增用户的时候我需要校验姓名、erp和年龄,而在修改用户的时候我只需要校验erp。
又或者,部门A的员工的年龄不能低于22岁,无上限;而部门B的员工年龄不能高于35岁,无下限。
难道我们需要根据每一个场景都增加一个Bean嘛?会不会有点太浪费?
不用的!这里提供了一个 分组 的概念,不同的规则可以划分到不同的组里面,校验的时候选择相应的组,就会只校验该组下面的所有规则。
定义两个接口 UserValidGroupOne
和 UserValidGroupTwo
,作为两个分组。
属性前写相应注解增加校验规则,注解里面的 groups
属性表示这条规则属于哪个分组,不加 groups
则表示在使用 Deafault
规则时起作用。
比如上面代码中描述的是:
name和erp字段的校验规则同属于两个分组。
age字段的校验规则,在分组1中不能小于22,而在分组2中不能大于35。
如上,在Controller的接口参数(刚定义的Bean)之前添加 @Validated
注解,注意不是 在【对Object的属性进行校验】时讲的 @Valid
注解。
在 @Validated
的 value
属性上注明要使用的规则分组。
可写多个分组,但是只有第一个分组才生效。
若使用 @Valid
则表示使用 默认 校验规则。
自定义注解
虽然Hibernate Validator提供了基本上所有常用的校验规则,可还是有些场景不能满足。
比如说,现在需要一个校验规则,一个List中不能包含null。Hibernate Validator并没有提供相应注解。
这时候就需要我们自定义注解,来扩展工具,满足我们自己的需求。
首先定义自定义注解 @ListNotHasNull
,校验List中不能含有null元素,注明其注解实现类为 ListNotHasNullValidatorImpl.class
。
接下来编写实现类的逻辑。
自定义注解的实现类实现了 ConstraintValidator
接口。
重要的是要重写 isValid
方法,其中的逻辑就是需要的校验规则。
接下来是测试用例。
家庭成员 familyMembers
是一个List,其中每一个元素都是 FamilyMember
类。
在 familyMembers
上增加刚才自定义的 @ListNotHasNull
注解。
ps. 此处加 @Valid
注解的原因是注明要递归校验,加上这个注解就会递归校验List中每个元素 FamilyMember
的属性是否符合其内部定义规则。
同样,在Controller的接口参数(刚定义的Bean)之前添加 @Valid
注解,校验不通过则抛出异常。
Spring validator方法级别的校验
JSR和Hibernate Validator的校验只能对Object的属性进行校验,不能对单个的参数进行校验。
Spring在此基础上进行了扩展,添加了 MethodValidationPostProcessor
拦截器,可以实现对方法参数的校验。
首先需要将 MethodValidationPostProcessor
注入到Spring容器中。
这里是通过Java Bean的方式,用 @Bean
注解,将 MethodValidationPostProcessor
注入到Spring容器中的。
也可以通过配置 xml
文件的方式,根据项目的需要选择使用。
需要在Controller类的上方添加 @Validated
注解,然后在接口方法的每一个参数前面添加相应的校验规则注解。
这样方法级别的校验就比较 灵活 了不是~
异常处理
之前一直在说,校验不通过的时候会 抛出异常,具体异常如何处理请根据自己的项目需要来。
但具体都抛出哪些异常,如何处理,我这边在写测试用例的时候捕获到了如下 三类 异常:
org.springframework.validation.BindException
org.springframework.web.bind.MethodArgumentNotValidException
javax.validation.ConstraintViolationException
推荐 使用 @ControllerAdvice
搭配 @ExceptionHandler
来捕获Controller层抛出来的异常。
写了简单的处理逻辑,仅供参考。
结语
安利了这么多,觉得好使不?
那必须好使啊~~~
部门在我的安利下所有新项目都在用 Hibernate Validator 参数校验器,经过了多种线上环境验证。大家就放心去用吧~
最后,有问题的话咱们共同探讨~ 共同学习~ 共同进步哈~
版权声明: 本文为 InfoQ 作者【HelloLittleRain】的原创文章。
原文链接:【http://xie.infoq.cn/article/ab5d6af967038daf3b526b9df】。文章转载请联系作者。
评论