java - JSR-303 共享继承对象验证

标签 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 ceo;

   @Valid
   private TechManager techManager;
   //getters and setters
}

在上面的示例中,phoneNumber 是 CEO 和 TechManager 之间的共享对象。

如何验证这一点,以便 CEO 具有可选性而 TechManager 具有强制性 phoneNumber ?

最佳答案

根据 Bean Validation Specification 1.0Bean 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 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。如果需要,我们可以通过为 User 类的所有字段定义组来获取所有约束:

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 组并定义 User 类约束,如下所示:

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;
}

关于java - JSR-303 共享继承对象验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54672156/

相关文章:

java - 覆盖动态创建的各个 JTable 单元格的单元格编辑器

java - 在j2me中显示alert然后跳转到另一个窗体

java - Sonarlint投诉日志写入方法

jsf - 关于 Bean 验证与 JSF 验证的问题?

java - 确定类和属性约束 JSR303 bean 验证

java - 获取EventHubException : Connection aborted when I create TWO instances of EventHubClient

java - Spring:保存登录的用户 session

jpa - 如何将javax.validation导入我的Java SE项目?

spring - 如何使用 spring 存储库进行 bean 验证?

kotlin - 使用 NotBlank 注释在 Kotlin 代码中不起作用