- 添加依赖包
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.10.Final</version>
</dependency>
<!--hibernate-validator 6.0.10.Final 的依赖-->
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.1-b09</version>
</dependency>
2. Hibernate已经实现的校验
3. 自定义Validator
先定义注解:
@Documented
@Constraint(validatedBy = { EnumValueValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(List.class)
public @interface EnumValue {
Class<? extends Enum<?>> enumClass();
String enumMethod();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String message() default "";
/**
* Defines several {@code @NotBlank} annotations on the same element.
*/
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface List {
EnumValue[] value();
}
}
再定义注解对应的Validator:
public class EnumValueValidator implements ConstraintValidator<EnumValue, Object>{
private Class<? extends Enum<?>> enumClass;
private String enumMethod;
public void initialize(EnumValue enumValue) {
this.enumClass = enumValue.enumClass();
this.enumMethod = enumValue.enumMethod();
}
/* (non-Javadoc)
* @see javax.validation.ConstraintValidator#isValid(java.lang.Object, javax.validation.ConstraintValidatorContext)
*/
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
if(value == null){
return Boolean.FALSE;
}
try {
Method validateMethod = this.enumClass.getMethod(this.enumMethod, value.getClass());
if(!Boolean.TYPE.equals(validateMethod.getReturnType()) && !Boolean.class.equals(validateMethod.getReturnType())){
throw new RuntimeException("method type error");
}
if(!Modifier.isStatic(validateMethod.getModifiers())){
throw new RuntimeException("method is not static");
}
Boolean result = (Boolean)validateMethod.invoke(null, value);
return result == null ? false : result;
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
intialize方法,在接口中默认是空实现。需要重写。
4. 应用
public class SignReq extends BaseReq{
@NotBlank
@Length(max=21)
private String cardNo;
@NotBlank
@Length(max=100)
private String userName;
@Pattern(regexp="^$|^\\d{11}$")
private String mobile;
@NotBlank
@Length(max=20)
private String idNo;
@NotBlank
@EnumValue(enumClass=IdTypeEnum.class, enumMethod="validateIdType")
private String idType;
。。。。。
}
public class HibernateValidatorTest {
public static void main(String[] args) {
SignReq req = new SignReq();
req.setIdType("1");
Validator validator = Validation.byProvider(HibernateValidator.class).configure().buildValidatorFactory().getValidator();
Set<ConstraintViolation<SignReq>> constraintViolationSet = validator.validate(req);
for(ConstraintViolation<SignReq> constraintViolation : constraintViolationSet){
if("com.validator.EnumValue".equals(constraintViolation.getConstraintDescriptor().getAnnotation().annotationType().getName())){
throw new RuntimeException(constraintViolation.getPropertyPath() + "error ");
}
}
}
}
Validate方法返回Set<ConstraintViolation>,所有校验不合格的都会放到这个set一起返回,如果希望一次只返回一个校验错误的参数,可以通过设置failFast为true:
Validator validator = Validation.byProvider(HibernateValidator.class).configure().failFast(true).buildValidatorFactory().getValidator();