Java JSR-303共享继承对象验证
假设我们有这样的结构:Java JSR-303共享继承对象验证,java,bean-validation,Java,Bean 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
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
字段,并以您需要的方式为每个子类定义验证注释。在这种情况下,应该覆盖getter和setter。您可以在子类中隐藏私有字符串phoneNumber
字段,并按照需要的方式为每个子类定义验证注释。在这种情况下,应该覆盖getter和setter。根据两者,您可以使用验证组
您可以创建自己的组层次结构。例如,每个字段一个组,为角色收集一个组:
首先,声明要为其配置验证的组
// 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 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 {
}
现在您可以定义Company类并检查验证是如何工作的
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。如果需要,我们可以通过为用户类的所有字段定义组来获得所有约束:
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 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;
}
根据两者,您可以使用验证组
您可以创建自己的组层次结构。例如,每个字段一个组,为角色收集一个组:
首先,声明要为其配置验证的组
// 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 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 {
}
现在您可以定义Company类并检查验证是如何工作的
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。如果需要,我们可以通过为用户类的所有字段定义组来获得所有约束:
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 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;
}
我不想做黑客。如果有很多字段,这是一个非常糟糕的解决方案。它破坏了你的结构视图我不想做黑客。如果有很多字段,这是一个非常糟糕的解决方案。它破坏了您的结构视图正如我阅读文档时所述,GroupSequence只是对Construction进行评估的顺序。现在假设TechManager位于另一个对象bean中,而不是公司(前员工)。那么,您的解决方案将不起作用,因为定义的序列仅对公司场景有用!我不确定我是否完全理解这个案子。GroupSequence用于TechManager,不用于公司。任何方式GroupSequence都不仅仅用于设置订单。规范中:“要重新定义类的默认值,请在类上放置@GroupSequence注释;该序列表示组的序列,并用默认值替换该类。”因此,我在示例中添加了Stuff类。我想,您没有理解我的意思。想象一下,除了上面定义的所有类之外,还有另一个类callstaff。在该类中,我们再次定义了这两个或其中一个对象(TechManager/CEO)。现在,如果有专门针对TechManager的组验证器(例如:EmailAddressMandatory.class),那么当PhoneNumberIsMandatory.class为硬编码时,您将如何用EmailAddressMandatory.class替换PhoneNumberIsMandatory.class?我需要对此进行解释。我正在寻找一种方法,用一个组接口(例如:UserChecker.class)验证这些类中的所有字段,如果其中一个子项是“instanceOf”某物,我会排除一个特定字段,因为它不需要验证是的,谢谢。如果需要验证所有约束,可以使用此构造验证器.validate(staff、PhoneNumberIsMandatory.class、EmailIsMandatory.class)。或使用Spring进行@Validated({PhoneNumberIsMandatory.class,EmailIsMandatory.class})。但它打破了一些封装。当然,在这种情况下,您可以选择任何组集进行验证。Sry,但我现在没有足够的时间,稍后我会改进答案。当我阅读文档时,GroupSequence只是对Construction进行评估的顺序。现在假设TechManager位于另一个对象bean中,而不是公司(前员工)。那么,您的解决方案将不起作用,因为定义的序列仅对公司场景有用!我不确定我是否完全理解这个案子。GroupSequence用于TechManager,不用于公司。任何方式GroupSequence都不仅仅用于设置订单。规范中:“要重新定义类的默认值,请在类上放置@GroupSequence注释;该序列表示组的序列,并用默认值替换该类。”因此,我在示例中添加了Stuff类。我想,您没有理解我的意思。想象一下,除了上面定义的所有类之外,还有另一个类callstaff。在该类中,我们再次定义了这两个或其中一个对象(TechManager/CEO)。现在,如果有专门针对TechManager的组验证器(例如:EmailAddressMandatory.class),那么当PhoneNumberIsMandatory.class为硬编码时,您将如何用EmailAddressMandatory.class替换PhoneNumberIsMandatory.class?我需要对此进行解释。我正在寻找一种方法,通过一个组接口(例如:UserChecker.class)和I验证这些类中的所有字段