介紹
JSR-303 是JAVA EE6 中的一項子規范,叫做Bean Validation,Hibernate Validator 是 Bean Validation 的參考實現,提供了 JSR 303 規范中所有內置 constraint 的實現,除此之外還有一些附加的 constraint。
簡單校驗
添加maven依賴
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.17.Final</version>
</dependency>
hibernate-validator還依賴以下兩個
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
實體類
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
public class User {
@NotBlank(message = "用戶名不能為空")
private String username;
@NotBlank(message = "密碼不能為空")
private String password;
@NotBlank(message = "密碼不能為空")
@Pattern(regexp = "^1([34578])\\d{9}$", message = "手機號格式錯誤")
private String mobile;
@NotBlank(message = "性別不能為空")
private String gender;
@NotNull(message = "年齡不能為空")
@Range(min = 5, max = 90, message = "年齡必須在5-90之間")
private Integer age;
private List<Address> addressList;
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
static class Address {
private String province;
private String city;
private String region;
}
}
public class Client {
public static void main(String[] args) {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintViolationSet = validator.validate(user);
for (ConstraintViolation<User> constraintViolation : constraintViolationSet) {
System.out.println(constraintViolation.getMessage());
}
}
}
Validation會通過SPI的方式找到所有ValidationProvider接口的實現,自然就找到hibernate-validator的實現HibernateValidator了。
當然我們也可以自己指定實現,自定義配置
public class Client {
public static void main(String[] args) {
Validator validator = Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(true) //有一個失敗就停止檢查
.buildValidatorFactory()
.getValidator();
User user = new User();
Set<ConstraintViolation<User>> constraintViolationSet = validator.validate(user);
for (ConstraintViolation<User> constraintViolation : constraintViolationSet) {
System.out.println(constraintViolation.getMessage());
}
}
}
級聯校驗
實體類
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
public class User {
@NotBlank(message = "用戶名不能為空")
private String username;
@NotBlank(message = "密碼不能為空")
private String password;
@NotBlank(message = "密碼不能為空")
@Pattern(regexp = "^1([34578])\\d{9}$", message = "手機號格式錯誤")
private String mobile;
@NotBlank(message = "性別不能為空")
private String gender;
@NotNull(message = "年齡不能為空")
@Range(min = 5, max = 90, message = "年齡必須在5-90之間")
private Integer age;
@Valid
@NotEmpty(message = "地址不能為空")
private List<Address> addressList;
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
static class Address {
@NotBlank(message = "省不能為空")
private String province;
@NotBlank(message = "市不能為空")
private String city;
@NotBlank(message = "區不能為空")
private String region;
}
}
使用Valid注解實現級聯校驗
public class Client {
public static void main(String[] args) {
Validator validator = Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(false) //有一個失敗就停止檢查
.buildValidatorFactory()
.getValidator();
User user = new User();
user.setAddressList(Collections.singletonList(new Address()));
Set<ConstraintViolation<User>> constraintViolationSet = validator.validate(user);
for (ConstraintViolation<User> constraintViolation : constraintViolationSet) {
System.out.println(constraintViolation.getMessage());
}
}
}
分組校驗
實體類
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
public class User {
@NotBlank(message = "用戶名不能為空")
private String username;
@NotBlank(message = "密碼不能為空")
private String password;
@NotBlank(message = "密碼不能為空")
@Pattern(regexp = "^1([34578])\\d{9}$", message = "手機號格式錯誤")
private String mobile;
@NotBlank(message = "性別不能為空")
private String gender;
@NotNull(message = "年齡不能為空")
@Range(min = 18, max = 90, message = "年齡必須在18-90之間", groups = Adult.class)
@Range(min = 5, max = 17, message = "年齡必須在5-17之間", groups = Minor.class)
private Integer age;
private List<Address> addressList;
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
static class Address {
private String province;
private String city;
private String region;
}
/**
* 成年人
*/
interface Adult {
}
/**
* 未成年人
*/
interface Minor {
}
}
不設置分組,默認為Default分組
public class Client {
public static void main(String[] args) {
Validator validator = Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(false) //有一個失敗就停止檢查
.buildValidatorFactory()
.getValidator();
User user = new User();
user.setAge(7);
Set<ConstraintViolation<User>> constraintViolationSet = validator
.validate(user, Default.class, Adult.class); // 設置要校驗的分組
for (ConstraintViolation<User> constraintViolation : constraintViolationSet) {
System.out.println(constraintViolation.getMessage());
}
}
}
不設置也會添加一個默認分組Default
自定義校驗器
校驗注解
/**
* 當前值必須在給定的列表中
*/
@Target({FIELD})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {ListRangeValidatorForString.class})
public @interface ListRange {
String message() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String[] value() default {};
}
校驗器
public class ListRangeValidatorForString implements ConstraintValidator<ListRange, String> {
private String[] range;
@Override
public void initialize(ListRange listRange) {
this.range = listRange.value();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (Objects.isNull(value)) {
return true;
}
return Arrays.asList(range).contains(value);
}
}
實體類
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
public class User {
@NotBlank(message = "用戶名不能為空")
private String username;
@NotBlank(message = "密碼不能為空")
private String password;
@NotBlank(message = "密碼不能為空")
@Pattern(regexp = "^1([34578])\\d{9}$", message = "手機號格式錯誤")
private String mobile;
@NotBlank(message = "性別不能為空")
@ListRange(value = {"male", "female"}, message = "性別必須在[male,female]之間")
private String gender;
@NotNull(message = "年齡不能為空")
@Range(min = 5, max = 90, message = "年齡必須在5-90之間")
private Integer age;
private List<Address> addressList;
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
static class Address {
private String province;
private String city;
private String region;
}
}
性別必須在male和female之間
public class Client {
public static void main(String[] args) {
Validator validator = Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(false) //有一個失敗就停止檢查
.buildValidatorFactory()
.getValidator();
User user = new User();
user.setAge(7);
user.setGender("ss");
Set<ConstraintViolation<User>> constraintViolationSet = validator.validate(user);
for (ConstraintViolation<User> constraintViolation : constraintViolationSet) {
System.out.println(constraintViolation.getMessage());
}
}
}
hibernate-validator會先找內置的注解校驗器,找不到就找自定義的校驗器。