本文参考自:http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/html
1. Field-Leveljava
基于属性的校验git
public class User{ [@NotNull](https://my.oschina.net/notnull) private String name; }
2. Property-Levelweb
基于getter的校验正则表达式
public class User{ private String name; [@NotNull](https://my.oschina.net/notnull) public String getName(){ return name; } }
3. Container Elementspring
容器校验ide
public class User{ // 集合中元素须长度 > 2 private List<@Length(min = 3) String> roles; }
4. Class-Levelspring-boot
类校验ui
// 声明注解 @Target({TYPE, ANNOTATION_TYPE}) @Retention(RUNTIME) @Constraint(validatedBy = {UserNameNotMatchValidator.class}) @Documented public @interface UserNameNotMatch{ String message() default "用户不匹配"; Class<?>[] groups() default {}; String allowName() default "admin"; Class<? extends Payload>[] payload() default {}; }
// 编写具体的校验类 public class UserNotMatchValidator implements ConstraintValidator<UserNotMatch, User> { private String allowName; @Override public void initialize(UserNotMatch constraintAnnotation) { allowName = constraintAnnotation.allowName(); } @Override public boolean isValid(User user, ConstraintValidatorContext constraintValidatorContext) { if (allowName.equals(user.getName())) { return true; } else { // 屏蔽默认错误信息 constraintValidatorContext.disableDefaultConstraintViolation(); constraintValidatorContext.buildConstraintViolationWithTemplate("普通用户不容许操做").addConstraintViolation(); return false; } } }
@UserNameNotMatch public class User{ private String name; }
5. Constraint inheritancespa
约束继承:当一个类继承另外一个类或者实现一个接口,超类中声明的约束与该类自己声明的约束一样有效
public class User{ @NotNull private String name; } public class Person extends User{ @NotNull private String sex; }
6. Object graphs
public class Role{ @NotNull private String auth; } public class User{ @Valid // 标记该注解才会进行校验Role对象,不然只校验User.role @NotNull private Role role; }
public class Role{ private String auth; } public class User{ private Set<@NotNull @Valid Role> roleSet; }
手动建立Validator
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator();
Spring Boot
引入spring-boot-starter-web,该依赖中包含 hibernate-validator,自动装配Validator Bean
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
注入Validator (javax.validation)
@Autowired private Validator validator
验证
Validator#validate(T clazz): 校验类(@Valid 仅在使用该方法时有效) Validator#validateProperty(T clazz,String propertyName): 校验属性 Validator#validateValue(T clazz,String propertyName, String value): 校验属性值
示例
Set<ConstraintViolation<T>> violationSet = validator.validate(tClass); violationSet.forEach(userConstraintViolation -> log.warn("Validation Err Bean={}, Property = {},Msg = {}", userConstraintViolation.getRootBeanClass(), userConstraintViolation.getPropertyPath(), userConstraintViolation.getMessage()));
ConstraintViolation
ConstraintViolation#getPropertyPath(): 属性名称 ConstraintViolation#getMessage(): 错误信息
BigDecimal
, BigInteger
, CharSequence
, byte
, short
, int
, long
)BigDecimal
, BigInteger
, CharSequence
, byte
, short
, int
, long
)BigDecimal
, BigInteger
, byte
, short
, int
, long
)BigDecimal
, BigInteger
, byte
, short
, int
, long
)CharSequence
, Collection
, Map and arrays
)BigDecimal
, BigInteger
, byte
, short
, int
, long
)BigDecimal
, BigInteger
, byte
, short
, int
, long
)BigDecimal
, BigInteger
, byte
, short
, int
, long
)BigDecimal
, BigInteger
, byte
, short
, int
, long
)CharSequence
,Collection
, Map and arrays
)ValidationMessages.properties
默认状况下使用JVM默认的语言环境,也可将本地化的ValidationMessages.properties添加到classpath下,覆盖默认语言环境下的配置
@Size( min = 2, max = 14, message = "The license plate '${validatedValue}' must be between {min} and {max} characters long" ) private String licensePlate;
Car car = new Car(); car.setLicensePlate("A"); message = validator.validateProperty( car, "licensePlate" ) .iterator() .next() .getMessage(); assertEquals( "The license plate 'A' must be between 2 and 14 characters long", message
);
public class Car { @NotNull private String manufacturer; @NotNull @Size(min = 2, max = 14) private String licensePlate; @Min(2) private int seatCount; @AssertTrue( message = "The car has to pass the vehicle inspection first", groups = CarChecks.class ) private boolean passedVehicleInspection; }
//manufacturer、licensePlate、seatCount则不会被校验 constraintViolations = validator.validate( car, CarChecks.class ); assertEquals( 1, constraintViolations.size() ); assertEquals( "The car has to pass the vehicle inspection first", constraintViolations.iterator().next().getMessage() );
定义Group
public interface Group { }
定义父类
public class GroupB { @NotNull(groups = Group.class) private String title; }
定义子类
public class GroupA extends GroupB{ @NotEmpty private String name; @NotNull(groups = Group.class) private String desc; }
验证
constraintViolations = validator.validate( group,Group.class ); assertThat( constraintViolations ).extracting( "message" ).containsOnly( "title must not be null", "desc must not be null" );
按照组序列的定义顺序,其中一个约束验证失败,其后的约束都不会获得验证
public interface Age { }
public interface Sing { }
@GroupSequence({Age.class, Sing.class}) public interface OrderChecks { }
定义校验类
public class Person { @Min(value = 18, groups = Age.class) private Long age; @AssertTrue(groups = Sing.class) private boolean sing; }
验证
Person person = new Person(); person.setAge(17L); person.setSing(false); validate(person, OrderChecks.class);
从新定义校验类
被@GroupSequence
标记的类必须声明在@GroupSequence
中,如示例中的Person.class
@GroupSequence({Sing.class, Age.class, Person.class}) public class Person { @Min(value = 18, groups = Age.class) private Long age; @AssertTrue(groups = Sing.class) private boolean sing; }
验证
Person person = new Person(); person.setAge(17L); person.setSing(false); validate(person);
public class PersonGroupSequenceProvider implements DefaultGroupSequenceProvider<Person> { @Override public List<Class<?>> getValidationGroups(Person person) { List<Class<?>> defaultGroupSequence = new ArrayList<>(); // 必须包含类自己 defaultGroupSequence.add(Person.class); if (null != person) { defaultGroupSequence.add(Sing.class); defaultGroupSequence.add(Age.class); } return defaultGroupSequence; } }
@GroupSequenceProvider(PersonGroupSequenceProvider.class) public class Person { @Min(value = 18, groups = Age.class) private Long age; @AssertTrue(groups = Sing.class) private boolean sing; }
public class Person { @Min(value = 18, groups = Age.class) private Long age; @AssertTrue(groups = Sing.class) private boolean sing; @NotEmpty(groups = Sing.class) private List<String> songs; }
public class Company { @Valid @ConvertGroup(from = Sing.class, to = Age.class) private Person person; }
验证
Company company = new Company(); Person person = new Person(); person.setAge(17L); person.setSing(false); person.addSong("Trouble is a friend"); company.setPerson(person); // 验证时传递的组是Sign.class,因为Company#person 定义了@ConvertGroup(from = Sing.class, to = Age.class),最终验证的组是Age.class validate(company, Sing.class);