【问题标题】:What is best approach to validate a Java bean against custom validation rules?根据自定义验证规则验证 Java bean 的最佳方法是什么?
【发布时间】:2016-09-22 11:45:43
【问题描述】:
public class User {
    private String name;
    private Integer age;
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return this.age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

在这里,我想使用在数据库中为每个字段定义的自定义规则集来验证这些字段。

例如验证 name 字段的长度 - 不同公司的长度验证可能不同。

场景: 对于公司 x,名称字段的最大长度可以是 20。 对于公司 y,名称字段的最大长度可以是 30。 如何应用此验证标准运行时?

【问题讨论】:

    标签: java validation


    【解决方案1】:

    我看到至少两种方法

    BeanValidation

    使用来自javax.validation.constraints packagehttps://docs.oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html 的注释来注释您的域对象的字段(您需要验证的字段,在您的情况下为用户)

    要执行验证,您需要获取 javax.validation.Validator 的实例 并使用它。

    示例代码

    void validate() {
            LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
            Set<ConstraintViolation<Msisdn>> violations = localValidatorFactoryBean.getValidator().validate(this);
            if (!violations.isEmpty()) {
                throw new ConstraintViolationException(violations);
            }
        }
    

    它需要 Spring 框架。请注意,构造 LocalValidatorFactoryBean 是一个昂贵的过程。

    通常,LocalValidatorFactoryBean 应该在应用程序启动时构造一次。

    javax.xml.validation.Validator 在需要的地方应该是@Autowired

    Spring Framework+Spring Boot 将为您管理所有这些细节。

    也可以在没有 Spring 的情况下使用 java 验证。强制组件是 Validation Provider(JDK 只定义接口,没有实现)。 Hibernate Validator 是样本验证提供者。

    在这种方法中,您只能在 Spring 管理的类(服务、控制器等)中执行验证。

    这不是在构造函数中验证的可行解决方案,在静态方法中。

    番石榴前置条件

    当我需要从构造函数执行验证时,我使用了它。

    查看 Guava 库中的先决条件 https://github.com/google/guava/wiki/PreconditionsExplained

    它公开了类似的功能

     Preconditions.checkNotNull(value, "value cannot be null");
     Preconditions.checkArgument(..)
    

    您可以在构建器中验证设置器、构造器、build() 方法中的参数 - 每次对象构建完成并且需要检查不变量时。

    在这种情况下,只需要 Guava 库。它与 Java Validation API 或实现无关。

    条件验证

    如果你希望你的验证依赖于上下文(不仅仅是你正在验证的类),那么验证规则不应该放在你正在验证的类上。

    在 Spring 中,您可以将 Validator 编写为外部类。

    public class PersonValidator implements Validator {
    
        public boolean supports(Class clazz) {
            return Person.class.equals(clazz);
        }
    
        public void validate(Object obj, Errors e) {
            ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
            Person p = (Person) obj;
            if (p.getAge() < 0) {
                e.rejectValue("age", "negativevalue");
            } else if (p.getAge() > 110) {
                e.rejectValue("age", "too.darn.old");
            }
        }
    }
    

    更多详情请见http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#validator

    同样的原则(带有验证逻辑的外部类)可以应用于 Guava。

    然后在您的业务逻辑中,您将能够选择和使用正确的验证器。

    【讨论】:

    • 使用 Java Bean Validation 库既不需要 Spring 也不需要 Guava,尽管它们都可以使用它。
    • 真的。但我的代码示例使用的是 Spring 组件 LocalValidatorFactoryBean。第二个示例(番石榴)与 Java Bean Validation 无关。更新了答案,详细说明了每个场景的依赖关系。
    • 其实使用Java Bean Validation需要一个JSR 303 framework; Spring 不是这样的框架——它是一个 DI 框架。它提供了对 JSR 303 的包装器,以便更方便地使用。
    • 真的。回答 aleady 状态“也可以在没有 Spring 的情况下使用 java 验证”。
    • 我的观点是 Spring 与 JSR 303 的关系与与 HTTP 的关系一样多。我不太清楚为什么会提到它。这就像说“为了在 Java 中添加两个数字,只需添加 Jython 库并执行这个简单的脚本” - 虽然它可能会达到预期的效果,但它有点像 sledgehammer -> nut 场景.
    猜你喜欢
    • 2013-08-18
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    • 2017-04-11
    • 2018-02-18
    相关资源
    最近更新 更多