bean validation
官网:http://beanvalidation.org
最新版本:http://beanvalidation.org/2.0/
Bean Validation
2.0
(JSR 380) 是java EE 8的一部分,但也可以用于以前的版本。
hibernate validation
官网:http://hibernate.org/validator/
官方文档:http://hibernate.org/validator/documentation/
jboss文档仓库:https://docs.jboss.org/hibernate/validator/
最新中文版:https://docs.jboss.org/hibernate/validator/4.3/reference/zh-CN/html_single
hibernate validation
是bean validation目前最好的实现。
·强烈建议看官方文档
,还是很容易理解的,看完中文再看英文。
兼容性
bean validation | hibernate validation | java | spring boot |
---|---|---|---|
1.1 | 5.4 series | 6+ | 1.5.*.RELEASE |
2.0 | 6.0 series | 8+ | 2.0.*.RELEASE |
简单示例
public class Car {
@NotNull
@Valid
private Person driver;
public Car(Person driver) {
this.driver = driver;
}
//getters and setters ...
}
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Car car = new Car(null);
Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car);
assertEquals(1, constraintViolations.size());
assertEquals("may not be null", constraintViolations.iterator().next().getMessage());
Spring Boot支持
引入hibernate validation依赖, Spring Boot会自动配置Validator。
在SpringMVC的Controller中加校验约束立即生效;在jsonrpc接口上需在类上加@Validated
注解,校验约束才会生效。
Spring Boot 1.5.*.RELEASE默认支持Bean Validation1.1,可强制使用Bean Validation2.0。
常用约束注解
看java api文档,都可以查看他们支持的数据类型,包路径javax.validation.constraints
,共22
个。
constraint | description |
---|---|
@Null | 必须为null |
@NotNull | 必须不为 null |
@AssertTrue | 必须为 true ,支持boolean、Boolean |
@AssertFalse | 必须为 false ,支持boolean、Boolean |
@Min(value) | 值必须小于value,支持BigDecimal、BigInteger,byte、shot、int、long及其包装类 |
@Max(value) | 值必须大于value,支持BigDecimal、BigInteger,byte、shot、int、long及其包装类 |
@DecimalMin(value) | 值必须小于value,支持BigDecimal、BigInteger、CharSequence,byte、shot、int、long及其包装类 |
@DecimalMax(value) | 值必须大于value,支持BigDecimal、BigInteger、CharSequence,byte、shot、int、long及其包装类 |
@Size(max=, min=) | 支持CharSequence、Collection、Map、Array |
@Digits (integer, fraction) | 必须是一个数字 |
@Negative | 必须是一个负数 |
@NegativeOrZero | 必须是一个负数或0 |
@Positive | 必须是一个正数 |
@PositiveOrZero | 必须是个正数或0 |
@Past | 必须是一个过去的日期 |
@PastOrPresent | 必须是一个过去的或当前的日期 |
@Future | 必须是一个将来的日期 |
@FutureOrPresent | 必须是一个未来的或当前的日期 |
@Pattern(regex=,flag=) | 必须符合指定的正则表达式 |
@NotBlank(message =) | 必须是一个非空字符串 |
必须是电子邮箱地址 | |
@NotEmpty | 被注释的字符串的必须非空 |
fail fast mode
https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-fail-fast
Hibernate Validator默认会校验完所有的属性,然后返回所有的验证失败信息。开启fail fast mode后,只要有一个验证失败,则返回验证失败信息。
java config.
@Configuration
public class ValidatorConfiguration {
@Bean
public Validator validator(){
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.failFast( true ) //同.addProperty( "hibernate.validator.fail_fast", "true" )
.buildValidatorFactory();
return validatorFactory.getValidator();
}
}
自定义验证器
实现一个自定义大小写的验证器
public enum CaseMode {
UPPER,
LOWER;
}
约束枚举.
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 定义validation constraint,拷贝一个@Max,改改就可以了
* 1)有几个参数就加几个值
* 2)@Constraint要指定后面的constraint validator
* 3) @List可以作用在List<T>中T上
*/
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Repeatable(List.class)
@Documented
@Constraint(validatedBy = CaseValidator.class)
public @interface Case {
String message() default "{javax.validation.constraints.Case.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
/**
* @return value the element must be upper or lower
*/
CaseMode value();
/**
* Defines several {@link Case} annotations on the same element.
*
* @see Case
*/
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@interface List {
Case[] value();
}
}
约束验证器.
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* constraint validator实现ConstraintValidator<A,B>即可
* A是validation constraint,B是要验证的对象
*/
public class CaseValidator implements ConstraintValidator<Case,String> {
private CaseMode caseMode;
@Override
public void initialize(Case caseMode) {
this.caseMode = caseMode.value();
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
//null values are valid
if (s == null) {
return true;
}
if (caseMode == CaseMode.UPPER) {
return s.equals(s.toUpperCase());
} else {
return s.equals(s.toLowerCase());
}
}
}
验证对象.
public class Demo{
@Case(value = CaseMode.LOWER,message = "userName必须是小写")
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
验证测试.
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<Demo>> validate = validator.validateValue(Demo.class,"userName","Hello");
Assertions.assertThat(validate.size()).isEqualTo(1);
Assertions.assertThat(validate.iterator().next().getMessage()).isEqualTo("userName必须是小写");
validate = validator.validateValue(Demo.class,"userName","hello");
Assertions.assertThat(validate.size()).isEqualTo(0);