yavi特性如下:
-
类型安全的约束,不支持的约束不能应用于错误类型
-
流畅且直观的API
-
适用于任何对象的约束。包括Java Beans、Records、Protocol Buffers、Immutables等
-
众多强大的内置约束
-
易于自定义约束
-
分组验证,条件验证
-
在创建对象前对参数进行验证
-
支持API,以及结合验证结果和验证器的功能,融入了函数式编程的概念
<dependency>
<groupId>am.ik.yavi</groupId>
<artifactId>yavi</artifactId>
<version>0.14.4</version>
</dependency>
2.2 定义和获取核心验证器实例
可以通过am.ik.yavi.builder.ValidatorBuilder来定义和获取核心验证器am.ik.yavi.core.Validator。如下示例:
Validator<User> validator = ValidatorBuilder.<User>of()
.constraint(User::getName, "name", c -> c.notEmpty())
.constraint(User::getIdNo, "idNo", c -> c.notNull().greaterThanOrEqual(2).lessThanOrEqual(14))
.constraint(User::getAge, "age", c -> c.greaterThanOrEqual(18)).build()
该示例,我们对User对象定义了验证器Validator,分别对name,idno,age三个字段定义了约束条件。
使用示例:
@Test
public void testUser() {
User user = new User("", "xxx", 17) ;
ConstraintViolations violations = User.validator.validate(user) ;
if (!violations.isValid()) {
violations.forEach(violation -> {
System.err.printf("字段【%s】不正确, 错误信息: %s%n", violation.name(), violation.message()) ;
});
}
}
2.3 嵌套对象验证
可以使用nest方法将约束应用于嵌套字段。你可以委托给嵌套字段的Validator进行验证,也可以在嵌套字段内部定义一组约束。如下示例:
// 实体对象定义如下
public class Address {
private City city;
private Country country;
// getters, setters, construct
}
public class City {
private String name ;
// getters, setters, construct
}
public class Country {
private String name ;
// getters, setters, construct
}
public interface AddressValidator {
Validator<Country> countryValidator = ValidatorBuilder.<Country> of()
.constraint(Country::getName, "name", c -> c.notEmpty().greaterThanOrEqual(2))
.build();
Validator<City> cityValidator = ValidatorBuilder.<City> of()
.constraint(City::getName, "name", c -> c.notEmpty())
.build();
Validator<Address> validator = ValidatorBuilder.<Address> of()
.nest(Address::getCountry, "country", countryValidator)
.nest(Address::getCity, "city", cityValidator)
.build() ;
Validator<Address> validator_2 = ValidatorBuilder.<Address> of()
.nest(Address::getCountry, "country",
b -> b.constraint(Country::getName, "name", c -> c.notEmpty()))
.nest(Address::getCity, "city",
b -> b.constraint(City::getName, "name", c -> c.notEmpty()))
.build();
}
@Test
public void testAddressValidator() {
City city = new City() ;
Country country = new Country("X") ;
Address address = new Address(city, country) ;
ConstraintViolations violations = AddressValidator.validator.validate(address) ;
if (!violations.isValid()) {
violations.forEach(violation -> {
System.err.printf("字段【%s】不正确, 错误信息: %s%n", violation.name(), violation.message()) ;
});
}
}
2.4 集合验证
你可以使用forEach方法将约束应用于Collection / Map/ Array中的每个元素。与嵌套字段类似,可以委托给每个元素的Validator进行验证,也可以在元素内部定义一组约束。如下示例:
public class Person {
private final String name ;
// getters, setters, construct
}
public class PersonVO {
private final List<Person> persons;
public PersonVO(List<Person> persons) {
this.persons = persons;
}
public List<Person> getPersons() {
return persons ;
}
}
public interface PersonValidator {
Validator<Person> personValidator = ValidatorBuilder.<Person> of()
.constraint(Person::getName, "name", c -> c.notEmpty().greaterThanOrEqual(2))
.build();
Validator<PersonVO> validator = ValidatorBuilder.<PersonVO> of()
.forEach(PersonVO::getPersons, "persons", personValidator)
.build();
}
参考: