本文參考自: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);