- 一、概述
- 目的
在一个应用的不同层面(例如表现层到持久层),验证数据是一个是反复共同的任务。许多时候相同的验证要在每一个独立的验证框架中出现很多次。为了提升开发效率,阻止重复造轮子,于是形成了这样一套规范。
开发人员经常将验证逻辑直接绑定到域模型中,使用验证代码将域类与类本身的元数据绑定在一起。
2. 简要介绍
方法一:后端参数校验最简单的做法是直接在业务方法里面进行判断,当判断成功之后再继续往下执行。
优点:简单,直接
缺点:代码的耦合,冗余,不美观。
方法二:使用BeanValidation(JSR380)规则。
JSR-380是JAVAEE6中的一项子规范,叫做BeanValidation,官方参考实现是HibernateValidator。此实现与Hibernate ORM没有任何关系。JSR380用于对JavaBean中的字段的值进行验证。SpringMVC3.x之中也大力支持JSR-303,可以在控制器中对表单提交的数据方便地验证。可以使用注解的方式进行验证。
该规范定义了一个元数据模型,默认的元数据来源是注解(annotation)。针对该规范的验证API不是为某一个编程模型来开发的,因此它不束缚于Web或者持久化。
3. 概念
BeanValidation是一个运行时的数据验证框架,在验证之后验证的错误信息会被马上返回,是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面,就可以在需要校验的时候进行校验了。
4. 特点
- BeanValidation验证符合标准的Java规范
- 让您通过注释来表达对对象模型的约束
- 让您以可扩展的方式编写自定义约束
- 提供用于验证对象和对象图的api
- 提供用于验证参数和返回方法和构造函数值的api
- 运行在JavaSE上,但是集成在JavaEE6和以后;Bean验证2.0是JavaEE8的一部分
版本303,349,380(Bean Validation2)
5. 网站
- Java官网,The Java Community Process(SM) Program - JSRs: Java Specification Requests - detail JSR# 303
- hibernate官网,Page Redirection
- hibernateapi官方文档,http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-gettingstarted-createproject
- beanvalidation官方api文档,https://docs.oracle.com/javaee/6/api/javax/validation/constraints/package-summary.html
- beanvalidation官网,Jakarta Bean Validation - Home
- beanvalidation2官方学习文档,https://beanvalidation.org/2.0/spec/
二、BeanValidation具体注释
原生注释:
空检查 Booelan检查 长度检查 日期检查 数值检查 |
Hibernate扩展
- 三、简单使用
- 添加依赖
<!--jsr380--> <dependency> |
2. 简单的校验注释
packagecom.xxjz.java.com.xxjz.java.util.beanValid.pojo; |
3. 在springMVC框架中使用
@Controller |
4. 在java使用
Public static void main(String[]args){ |
- 四、高级功能
- 自定义校验注解
虽然jSR303和HibernateValidtor已经提供了很多校验注解,但是当面对复杂参数校验时,还是不能满足我们的要求,这时候我们就需要自定义校验注解。
a. 定义注解
packagecom.xxjz.validate.annotation; importjavax.validation.Constraint; importjavax.validation.Payload; importjava.lang.annotation.*; importstaticjava.lang.annotation.ElementType.*; importstaticjava.lang.annotation.ElementType.PARAMETER; importstaticjava.lang.annotation.RetentionPolicy.RUNTIME; /** *自定义参数校验注解 *校验List集合中是否有null元素 */ @Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD,ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint(validatedBy=ListNotHasNullValidatorImpl.class)此处指定了注解的实现类为ListNotHasNullValidatorImpl public@interfaceListNotHasNull{ /** *添加value属性,可以作为校验时的条件,若不需要,可去掉此处定义 */ intvalue()default0; Stringmessage()default"List集合中不能含有null元素"; Class<?>[]groups()default{}; Class<?extendsPayload>[]payload()default{}; /** *定义List,为了让Bean的一个属性上可以添加多套规则 */ @Target({METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER}) @Retention(RUNTIME) @Documented @interfaceList{ ListNotHasNull[]value(); } } |
b. 实现注解类:
packagecom.beiyan.validate.annotation; importorg.springframework.stereotype.Service; importjavax.validation.ConstraintValidator; importjavax.validation.ConstraintValidatorContext; importjava.util.List; /** *自定义注解ListNotHasNull的实现类 *用于判断List集合中是否含有null元素 */ @Service publicclassListNotHasNullValidatorImplimplementsConstraintValidator<ListNotHasNull,List>{ privateintvalue; @Override publicvoidinitialize(ListNotHasNullconstraintAnnotation){ //传入value值,可以在校验中使用 this.value=constraintAnnotation.value(); } publicbooleanisValid(Listlist,ConstraintValidatorContextconstraintValidatorContext){ for(Objectobject:list){ if(object==null){ //如果List集合中含有Null元素,校验失败 returnfalse; } } returntrue; } } |
c. 添加注解
publicclassUser{ /** *所拥有的书籍列表 */ @NotEmpty(message="所拥有书籍不能为空") @ListNotHasNull(message="List中不能含有null元素") @Valid privateList<Book>books; //gettersetter方法....... } |
2. 方法级别的校验
JSR和Hibernatevalidator的校验只能对Object的属性进行校验,不能对单个的参数进行校验,spring在此基础上进行了扩展,添加了MethodValidationPostProcessor拦截器,可以实现对方法参数的校验,实现如下:
a. 实例化MethodValidationPostProcessor
@Bean Public MethodValidationPostProcessor methodValidationPostProcessor(){ Return new MethodValidationPostProcessor(); } |
b. 在所要实现方法参数校验的类上面添加@Validated
@RestController @Validated publicclassValidateController{ } |
c. 在方法上面添加校验规则
@RequestMapping(value="/test",method=RequestMethod.GET) publicStringparamCheck(@Length(min=10)@RequestParamStringname){ System.out.println(name); returnnull; } |
d. 当方法上面的参数校验失败,spring框架就回抛出异常
{ "timestamp":1476108200558, "status":500, "error":"InternalServerError", "exception":"javax.validation.ConstraintViolationException", "message":"Nomessageavailable", "path":"/test" } |