来讲一下“hibernate-validator改进校验框架validator v0.4使用”的完整攻略。
什么是Hibernate-Validator?
Hibernate-Validator 是一款校验框架。这个框架的初衷是为了在 JavaBean 层面上提供一套统一、可重用的验证机制,使得我们在对 JavaBean 进行数据验证时能够更加方便、快捷、灵活。
为什么要改进校验框架?
虽然Hibernate-Validator 是一款很强大的校验框架,但是它并不完美。使用过程中也会存在一些问题,比如:
- 对于一些非基本类型的校验,在实现上有些复杂。
- 使用起来不是很方便,需要大量的注解。
所以,在实际的开发过程中,我们可能需要对 Hibernate-Validator 进行一些改进,以使其更加适合我们的实际需求。
改进
改进主要有两个方面,一个是简化校验逻辑,减少注解的使用;另一个是对于复杂类型的校验能够更加便捷。
简化校验逻辑
我们可以通过自定义注解,来简化校验逻辑。假设我们需要校验一个User对象,其中包含一个名字字段,这个字段的长度应该在1到10之间。原来的写法可能是这样:
public class User {
@Size(min = 1, max = 10)
private String name;
...
}
这里我们使用了 @Size 注解来进行校验。如果我们要在其他地方也需要对这个长度做校验,就需要再次在其他地方加上这个注解。代码冗余。
我们可以自定义注解,比如:
@Target({ METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = { UserNameValidator.class })
public @interface UserName {
String message() default "名字长度不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
然后使用这个注解来替换原来的 @Size 注解:
public class User {
@UserName
private String name;
...
}
这样,我们就可以将校验逻辑定义在一个地方,避免了代码重复。
对于复杂类型的校验能够更加便捷
使用 Hibernate-Validator 进行校验一个 List,原来的写法可能是这样:
public void validate(List<User> users) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
for (User user : users) {
Set<ConstraintViolation<User>> constraintViolations = validator.validate(user);
// ...
}
}
这里我们需要手动遍历List,将每个User对象拿出来进行校验。这种写法不仅代码量大,还不够优雅。
我们可以使用一个注解 @Valid,这个注解可以直接将List中的对象进行校验。代码大大简化:
public void validate(@Valid List<User> users) {
// ...
}
这个注解下文中会再次提到。
两条示例
我们举两个例子来说明 Hibernate-Validator 的使用方法和对其进行改进的方法。
示例一:校验日期格式
在开发过程中,我们可能需要对日期格式进行校验。Hibernate-Validator 中提供了一个注解 @Past,可以用来检查一个日期是否在当前时间之前。但是在实际场景中我们可能需要使用自己定义的日期格式来进行校验。
首先,我们自定义一个注解 DatePattern:
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = {DatePatternValidator.class})
public @interface DatePattern {
String message() default "日期格式不正确";
String pattern() default "yyyy-MM-dd";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Documented
public @interface List {
DatePattern[] value();
}
}
其中这个注解有两个属性:message表示验证失败时的错误信息;pattern表示日期格式。
然后编写一个实现校验逻辑的validator:
public class DatePatternValidator implements ConstraintValidator<DatePattern, String> {
private String pattern;
@Override
public void initialize(DatePattern constraintAnnotation) {
pattern = constraintAnnotation.pattern();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
return TimeUtil.checkDateFormat(value.trim(), this.pattern);
}
}
这里我们根据注解中的日期格式 pattern,使用 TimeUtil 工具类进行校验。TimeUtil.checkDateFormat() 的实现可以参考如下:
public static boolean checkDateFormat(String value, String format) {
try {
SimpleDateFormat sdf = new SimpleDateFormat(format);
sdf.setLenient(false);
sdf.parse(value);
return true;
} catch (ParseException e) {
return false;
}
}
这样,我们就可以使用 @DatePattern 注解来校验日期格式了:
public class Order {
@DatePattern(message = "日期格式不正确", pattern = "yyyy-MM-dd HH:mm:ss")
private String createTime;
// getter & setter
}
示例二:校验内嵌对象
Hibernate-Validator 可以直接对一个对象进行校验。但是如果这个对象中还包含了其它对象,或者是一个 List,我们还需要手动去遍历,对其内部进行校验。为了解决这个问题,我们可以使用 @Valid 注解。
假设我们有一个 User 对象,它包含了一个地址,地址中又包含了城市和省份信息:
public class User {
private String name;
@Valid
private Address address;
// getter & setter
}
public class Address {
private String city;
private String province;
// getter & setter
}
对于嵌套的对象,我们只需要在字段上使用 @Valid 注解,然后就可以进行递归校验了。
Set<ConstraintViolation<User>> constraintViolations = validator.validate(user);
这里我们使用了 Hibernate-Validator 提供的 validate 方法,这个方法内部会自动递归进行校验。
另外,如果我们要对一个 List 进行校验,也可以使用 @Valid 注解:
public class Order {
@NotNull(message = "订单不能为空")
@Size(min = 1, message = "订单至少包含一项")
@Valid
private List<OrderItem> orderItems;
// getter & setter
}
这样,就可以对 Order 对象中的 orderItems 进行校验了。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:hibernate-validator改进校验框架validator v0.4使用 - Python技术站