JSR-303 共享继承对象验证
JSR-303 Shared Inherited Object Validation
假设我们有这样的结构:
public class User {
@NotNull(message = "not available")
private String phoneNumber;
//getter and setter
}
public class CEO extends User{}
public class TechManager extends User{}
public class Company {
@Valid
private CEO ceo;
@Valid
private TechManager techManager;
//getters and setters
}
在上面的示例中,phoneNumber 是 CEO 和 TechManager 之间的共享对象。
如何以 CEO 可选且 TechManager 强制 phoneNumber 的方式验证这一点?
您可以隐藏子类中的 private String phoneNumber
字段,并按照您需要的方式为每个子类定义验证注释。在这种情况下,getter 和 setter 应该被覆盖。
根据Bean Validation Specification 1.0 and Bean Validation 2.0 Specification,您可以使用验证组。
您可以创建自己的组层次结构。例如,每个字段一组,并为角色收集一组:
首先,声明要配置验证的组。
// Define group for which phoneNumber will be mandatory
interface PhoneNumberIsMandatory {}
// Define group for which Email will be mandatory
interface EmailIsMandatory {}
// Define a TechManagerValidation group with includes PhoneNumberIsMandatory and EmailIsMandatory groups
interface TechManagerValidation extends PhoneNumberIsMandatory, EmailIsMandatory {}
让我们准备父 class 声明。您可以用一个组声明一个或多个字段。此外,您可以为一个字段声明一个或多个组。或者根本不声明组。
class User {
@NotNull(message = "Name nust be set")
public String name;
@NotNull(groups = {PhoneNumberIsMandatory.class}, message = "Phone number must be set")
public String phoneNumber;
@Email
@NotNull(groups = {EmailIsMandatory.class}, message = "Primary email must be set")
String primaryEmail;
@Email
@NotNull(groups = {EmailIsMandatory.class}, message = "Secondary email must be not null")
String secondaryEmail;
}
使用@GroupSequence 注释重新定义默认验证组。
@GroupSequence({TechManager.class, TechManagerValidation.class})
class TechManager extends User {
}
现在您可以定义公司 class 并检查验证的工作方式
class CEO extends User {
}
class Company {
@Valid
public CEO ceo;
@Valid
public TechManager techManager;
}
public class DemoApplication {
public static void main(String[] args) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Company company = new Company();
company.ceo = new CEO();
company.techManager = new TechManager();
System.out.println("Company: " + validator.validate(company));
}
}
请注意,默认组约束首先验证,如果其中任何一个失败,TechManagerValidation 将被跳过。如果需要,我们可以通过为 User class:
的所有字段定义组来获取所有约束
interface NameIsMandatory {}
interface PhoneNumberIsMandatory {}
interface EmailIsMandatory {}
interface TechManagerValidation extends NameIsMandatory, PhoneNumberIsMandatory, EmailIsMandatory {}
interface CeoValidation extends NameIsMandatory {}
class User {
@NotNull(groups = {NameIsMandatory.class}, message = "Name nust be set")
public String name;
@NotNull(groups = {PhoneNumberIsMandatory.class}, message = "Phone number must be set")
public String phoneNumber;
@Email
@NotNull(groups = {EmailIsMandatory.class}, message = "Primary email must be set")
String primaryEmail;
@Email
@NotNull(groups = {EmailIsMandatory.class}, message = "Secondary email must be not null")
String secondaryEmail;
}
@GroupSequence({TechManager.class, TechManagerValidation.class})
class TechManager extends User {
}
@GroupSequence({CEO.class, CeoValidation.class})
class CEO extends User {
}
class Company {
@Valid
public CEO ceo;
@Valid
public TechManager techManager;
}
public class DemoApplication {
public static void main(String[] args) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Company company = new Company();
company.ceo = new CEO();
company.techManager = new TechManager();
System.out.println("Company: " + validator.validate(company));
}
}
还有另一种方法,但我认为它破坏了封装。您可以删除 NameIsMandatory、PhoneIsMandatory 和 EmailIsMandatory 组并定义用户 class 约束,如下所示:
class User {
@NotNull(groups = {TechManagerValidation.class, CeoValidation.class}, message = "Name nust be set")
public String name;
@NotNull(groups = {TechManagerValidation.class}, message = "Phone number must be set")
public String phoneNumber;
@Email
@NotNull(groups = {TechManagerValidation.class}, message = "Primary email must be set")
String primaryEmail;
@Email
@NotNull(groups = {TechManagerValidation.class}, message = "Secondary email must be not null")
String secondaryEmail;
}
假设我们有这样的结构:
public class User {
@NotNull(message = "not available")
private String phoneNumber;
//getter and setter
}
public class CEO extends User{}
public class TechManager extends User{}
public class Company {
@Valid
private CEO ceo;
@Valid
private TechManager techManager;
//getters and setters
}
在上面的示例中,phoneNumber 是 CEO 和 TechManager 之间的共享对象。
如何以 CEO 可选且 TechManager 强制 phoneNumber 的方式验证这一点?
您可以隐藏子类中的 private String phoneNumber
字段,并按照您需要的方式为每个子类定义验证注释。在这种情况下,getter 和 setter 应该被覆盖。
根据Bean Validation Specification 1.0 and Bean Validation 2.0 Specification,您可以使用验证组。
您可以创建自己的组层次结构。例如,每个字段一组,并为角色收集一组:
首先,声明要配置验证的组。
// Define group for which phoneNumber will be mandatory
interface PhoneNumberIsMandatory {}
// Define group for which Email will be mandatory
interface EmailIsMandatory {}
// Define a TechManagerValidation group with includes PhoneNumberIsMandatory and EmailIsMandatory groups
interface TechManagerValidation extends PhoneNumberIsMandatory, EmailIsMandatory {}
让我们准备父 class 声明。您可以用一个组声明一个或多个字段。此外,您可以为一个字段声明一个或多个组。或者根本不声明组。
class User {
@NotNull(message = "Name nust be set")
public String name;
@NotNull(groups = {PhoneNumberIsMandatory.class}, message = "Phone number must be set")
public String phoneNumber;
@Email
@NotNull(groups = {EmailIsMandatory.class}, message = "Primary email must be set")
String primaryEmail;
@Email
@NotNull(groups = {EmailIsMandatory.class}, message = "Secondary email must be not null")
String secondaryEmail;
}
使用@GroupSequence 注释重新定义默认验证组。
@GroupSequence({TechManager.class, TechManagerValidation.class})
class TechManager extends User {
}
现在您可以定义公司 class 并检查验证的工作方式
class CEO extends User {
}
class Company {
@Valid
public CEO ceo;
@Valid
public TechManager techManager;
}
public class DemoApplication {
public static void main(String[] args) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Company company = new Company();
company.ceo = new CEO();
company.techManager = new TechManager();
System.out.println("Company: " + validator.validate(company));
}
}
请注意,默认组约束首先验证,如果其中任何一个失败,TechManagerValidation 将被跳过。如果需要,我们可以通过为 User class:
的所有字段定义组来获取所有约束interface NameIsMandatory {}
interface PhoneNumberIsMandatory {}
interface EmailIsMandatory {}
interface TechManagerValidation extends NameIsMandatory, PhoneNumberIsMandatory, EmailIsMandatory {}
interface CeoValidation extends NameIsMandatory {}
class User {
@NotNull(groups = {NameIsMandatory.class}, message = "Name nust be set")
public String name;
@NotNull(groups = {PhoneNumberIsMandatory.class}, message = "Phone number must be set")
public String phoneNumber;
@Email
@NotNull(groups = {EmailIsMandatory.class}, message = "Primary email must be set")
String primaryEmail;
@Email
@NotNull(groups = {EmailIsMandatory.class}, message = "Secondary email must be not null")
String secondaryEmail;
}
@GroupSequence({TechManager.class, TechManagerValidation.class})
class TechManager extends User {
}
@GroupSequence({CEO.class, CeoValidation.class})
class CEO extends User {
}
class Company {
@Valid
public CEO ceo;
@Valid
public TechManager techManager;
}
public class DemoApplication {
public static void main(String[] args) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Company company = new Company();
company.ceo = new CEO();
company.techManager = new TechManager();
System.out.println("Company: " + validator.validate(company));
}
}
还有另一种方法,但我认为它破坏了封装。您可以删除 NameIsMandatory、PhoneIsMandatory 和 EmailIsMandatory 组并定义用户 class 约束,如下所示:
class User {
@NotNull(groups = {TechManagerValidation.class, CeoValidation.class}, message = "Name nust be set")
public String name;
@NotNull(groups = {TechManagerValidation.class}, message = "Phone number must be set")
public String phoneNumber;
@Email
@NotNull(groups = {TechManagerValidation.class}, message = "Primary email must be set")
String primaryEmail;
@Email
@NotNull(groups = {TechManagerValidation.class}, message = "Secondary email must be not null")
String secondaryEmail;
}