Hibernate Validator 是 Bean Validation 的参考实现 。Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint。
1.maven中引入hibernate-validator对应的jar:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.1.Final</version>
</dependency>
2. Bean Validator内置的注解
Annotation | 支持的数据类型 | 作用 | Hibernate metadata impact |
@AssertFalse | Boolean, boolean | 判断关联属性是否为布尔值false | 没有 |
@AssertTrue | Boolean, boolean | 检查带注释的元素是否正确。 | 没有 |
@DecimalMax | BigDecimal, BigInteger, String, byte, short, int,long | 被注解的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示. | 没有 |
@DecimalMin | BigDecimal, BigInteger, String, byte, short, int,long | 被注解的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示. | 没有 |
@Digits(integer=, fraction=) | BigDecimal, BigInteger, String, byte, short, int,long | 校验整数位数和小数位数 | 对应的数据库表字段会被设置精度(precision)和准度(scale). |
@Future | java.util.Date, java.util.Calendar; | 检查给定的日期是否比现在晚. | 没有 |
@Max | BigDecimal, BigInteger, byte, short, int, long | 检查该值是否小于或等于约束条件中指定的最大值. | 会给对应的数据库表字段添加一个check的约束条件. |
@Min | BigDecimal, BigInteger, byte, short, int, | 检查该值是否大于或等于约束条件中规定的最小值. | 会给对应的数据库表字段添加一个check的约束条件. |
@NotNull | Any type | Checks that the annotated value is notnull. | 对应的表字段不允许为null. |
@Null | Any type | Checks that the annotated value is null. | 没有 |
@Past | java.util.Date, java.util.Calendar;
| 检查注解对象中的值表示的日期比当前早. | 没有 |
@Pattern(regex=, flag=) | String | 检查该字符串是否能够在match指定的情况下被regex定义的正则表达式匹配. | 没有 |
@Size(min=, max=) | String, Collection, Map and arrays | 校验对象的size。本文作者认为前提是该对象有size()方法,String除外。 | 对应的数据库表字段的长度会被设置成约束中定义的最大值. |
@Valid | Any non-primitive type | 递归的对关联对象进行校验, 如果关联对象是个集合或者数组, 那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验. | 没有 |
3. Hibernate Validator拓展的注解
Annotation | 支持的数据类型 | 作用 | Hibernate metadata impact |
@CreditCardNumber | String | 校验信用卡号码 | 没有 |
| String | 校验邮件地址 | 没有 |
@Length(min=, max=) | String | 功能同@Size,但是只支持String类型 | 对应的数据库表字段的长度会被设置成约束中定义的最大值. |
@NotBlank | String | 不为null,不为空值,不为全空格。功能强大于@NotEmpty | 没有 |
@NotEmpty | String,Collection,Map, arrays | 校验是否为null或者为空值。功能强于@NotNull | 没有 |
@Range(min=, max=) | BigDecimal,BigInteger,String, byte,short, int,long | 判断数值的范围,不仅支持数值类型,还支持字符串、字节等等类型 | 没有 |
@SafeHtml(whitelistType=, additionalTags=) | CharSequence | 无使用价值 | 没有 |
@ScriptAssert(lang=, script=, alias=) | Any type | 无使用价值 | 没有 |
@URL(protocol=, host=, port=, regexp=, flags=) | String | 根据RFC2396检查带注释的字符串是否有效的URL。如果指定了任意可选的参数协议、主机或端口,则相应的URL片段必须与指定的值匹配。可选的参数regexp和标志允许指定附加的正则表达式(包括udin)。正则表达式标志,URL必须与之匹配。................................................. | 没有 |
4. Validator框架拓展注解
Annotation | 支持的数据类型 | 作用 |
@NotEmptyPattern | String | 在字符串不为空的情况下,验证是否匹配正则表达式 |
@ListStringPattern | List<String> | 验证集合中的字符串是否满足正则表达式 |
@DateValidator | String | 验证日期格式是否满足正则表达式,Local为ENGLISH |
@DateFormatCheckPattern | String | 验证日期格式是否满足正则表达式,Local为自己手动指定 |
5. 对象图级联校验
Validator不仅能够校验单个实例对象,还可以校验完整的对象图。对于实例中的对象成员属性,注解上@Valid,就可以被关联校验。
6. 约束条件组合校验
在某些复杂的场景中, 可能还会有更多的约束条件被定义到同一个元素上面, 这可能会让代码看起来有些复杂, 另外, 如果在另外的类里面还有一个相同的属性, 我们可能还要把这些约束条件再拷贝到这个属性上, 但是这样做又违反了 DRY 原则.这个问题可以通过使用组合约束条件来解决.
@NotNull @NotBlank @Target( { ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = {}) @Documented public @interface NotNullAndValidCheck { String message() default "必须不为null且属性格式符合要求";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {}; } |
7.验证失败异常捕获
验证失败将会抛出BindException异常
BindingResult bindingResult = ((BindException) e).getBindingResult();
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
Map<String, String> errorMsg = new HashMap<>();
for (FieldError fieldError : fieldErrors) {
errorMsg.put(fieldError.getField(), fieldError.getDefaultMessage());
}
8.自定义注解
验证字符串被格式化成集合,验证集合的长度
@Target用于指定使用范围,该处限定只能在字段上使用
@Retention(RetentionPolicy.RUNTIME)表示注解在运行时可以通过反射获取到
@Constraint(validatedBy = xxx.class)指定该注解校验逻辑
8.1 验证的注解
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Constraint(validatedBy = FormatStrValidator.class)
public @interface FormateStr {
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String message() default "";
/**
* 分隔符
* @return
*/
String delimiter() default ",";
int min() default 0;
int max() default Integer.MAX_VALUE;
}
8.2 注解实现类
public class FormatStrValidator implements ConstraintValidator<FormateStr, String> {
private static final Log log = LoggerFactory.make();
private int min;
private int max;
private String delimiter;
@Override
public void initialize(FormateStr constraintAnnotation) {
min = constraintAnnotation.min();
max = constraintAnnotation.max();
delimiter = constraintAnnotation.delimiter();
validateParameters();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(StringUtils.isBlank(value)) {
return true;
}
int length = value.split(delimiter).length;
return length >= min && length <= max;
}
private void validateParameters() {
if ( min < 0 ) {
throw log.getMinCannotBeNegativeException();
}
if ( max < 0 ) {
throw log.getMaxCannotBeNegativeException();
}
if ( max < min ) {
throw log.getLengthCannotBeNegativeException();
}
}
}