官方文档
Hibernate Validation目前最新的稳定版本是:5.1.3。 下载地址官网地址官方英文使用手册官方中文使用手册地址 (中文版目前最新的是4.3版本)
具体用法可以参考官方文档。
1.依赖包:
J2SE环境下除了需要引入Hibernate Validation包外,还需要额外引入两个实现表达式语言的包。J2EE环境如果容器提供不需要再引入。下面是J2SE环境下的依赖包:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.4.Final</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
2. 校验工具类:
Validation类提供了三种方法来创建一个Validator的实例
此处我们重点介绍第一种方式,也是最常见的一种方式
//最普通的实现方式
factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
PS:如果需要设置校验器的工作模式,可以在生成Validator实例时指定其工作模式,其工作模式有两种
validator.failFast:快速失败返回模式(只要有一个验证失败,则返回异常)
validator.normal:普通模式(会校验完所有的属性,然后返回所有的验证失败信息)
validator = Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(true) //快速返回
.buildValidatorFactory()
.getValidator();
创建出来的Validator实例是线程安全的,可以缓存下来
3.约束的介绍
Beanvalidation的约束是通过java注解来标注的, 并且分为三种不同的注解类型
1. 字段级约束
当约束被定义在字段上的时候, 这个字段的值是通过字段访问策略来获取并验证的. 也就是说Bean Validation的实现者会直接访问这个实例变量而不会调用属性的访问器(getter) 即使这个方法存在.
Tip:这个字段的访问级别( private, protected 或者 public) 对此没有影响
Tip:静态字段或者属性是不会被校验的
2. 属性级别约束
和字段级别约束的区别是它的约束是定义在属性级别上的
并且只能定义在getter上面, 不能定义在setter上
3. 类级别约束
一个约束也能够被放在类级别上. 当一个约束被标注在一个类上的时候,这个类的实例对象被传递给ConstraintValidator. 当需要同时校验多个属性来验证一个对象或者一个属性在验证的时候需要另外的属性的信息的时候, 类级别的约束会很有用.
4.约束继承
如果要验证的对象继承某个父类或者实现了某个接口, 那么定义在父类或者接口中的约束会在验证这个对象的时候被自动加载。
5.对象图
BeanValidation Api不仅能够用来校验单个实例对象,还能够用来校验完整的对象图
要使用这个功能,只需要在一个有关联关系的字段或者属性上标注@Valid. 这样,如果一个对象被校验,那么它的所有的标注了@Valid的关联对象都会被校验.
关联校验也适用于集合类型的字段
如果标注了@Valid, 那么当主对象被校验的时候, 这些集合对象中的元素也会被校验
Tip:对象图校验的时候会忽略null, 所以一般需要加上@NotNull和@Valid
以下给出一个示例:
public class Author {
@NotBlank(message = "作者名称不能为空")
private String username;
@NotBlank
@Size(min = 6, max = 20,message = "密码必须在6和20之间")
private String password;
@NotBlank(message = "邮箱不能为空")
@Email
private String email;
@Min(0)
private int age;
@NotBlank(message = "地址不能为空")
@Size(max = 500)
private String address;
@Past
@NotNull(message = "出生日期不能为空")
private Date birthday;
@Valid
@NotNull
private List<Article> articles = new ArrayList<>();
get set方法省略
}
ConstrainViolation中的方法
getMessage():获取经过翻译的校验错误信息
getMessageTemplate():获取错误信息模板
getRootBean():获取被校验的根实体对象
getRootBeanClass():获取被校验的根实体类
getLeafBean():如果约束是添加在一个Bean上的,那么则返回这个bean的实例,如果约束是定义一个属性上的,则返回这个属性所属的bean的实例对象
getPropertyPath():从被验证的根对象到被验证的属性的路径
getInvalidValue():导致校验失败的值
getConstraintDescriptior():导致校验失败的约束定义
现在要对这个Author类做校验
author=new Author();
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Author>> validate = validator.validate(author);
for (ConstraintViolation<Author> authorConstraintViolation : validate) {
authorConstraintViolation.getMessage();
}
4. 自定义约束
有些情况下,Hibernate Validator自带的校验注解不满足需求时,我们可以自定义注解
5. 校验方法的入参
很多时候我们还想校验以下方法的入参,这个在Hibernate Validator校验框架也是支持的,此处先看看文档上给出的demo
public class Car {
public Car(@NotNull String manufacturer) {
//...
}
public Car(String manufacturer, String team) {
//...
}
public void drive(@Max(value = 75,message = "速度最大不能超过80") int speedInMph) {
//...
}
@Size(min = 1)
public List<Passenger> getPassengers() {
//...
return null;
}
生成校验工厂的方式等同于bean校验的,但是校验的实例是ExecutableValidator的实例,通过反射的方式获取需要检验的方法
ValidatorFactory factory = Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(true)
.buildValidatorFactory();
ExecutableValidator executableValidator = factory.getValidator().forExecutables();
Car object = new Car( "Morris" );
Method method = Car.class.getMethod( "drive", int.class );
Object[] parameterValues = { 80 };
Set<ConstraintViolation<Car>> violations = executableValidator.validateParameters(
object,
method,
parameterValues
);
assertEquals( 1, violations.size() );
System.out.println(violations.iterator().next().getMessage());
当然这只是一个demo,在实际项目中用途不是很大, 在实际项目中需要结合Spring AOP来使用。