简体   繁体   English

根据自定义验证规则验证Java Bean的最佳方法是什么?

[英]What is best approach to validate a Java bean against custom validation rules?

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

Here I want to validate these fields using custom rule set defined in database for each field. 在这里,我想使用数据库中为每个字段定义的自定义规则集来验证这些字段。

eg validate length of name field - length validation can be different for different companies. 例如,验证name字段的长度-不同公司的长度验证可以不同。

Scenario : For company x, max length of name field can be 20. For company y, max length of name field can be 30. How to apply this validation criteria runtime? 方案:对于x公司,名称字段的最大长度可以为20。对于y公司,名称字段的最大长度可以为30。如何应用此验证条件运行时?

I see at least two approaches 我至少看到两种方法

BeanValidation BeanValidation

Annotate field of your domain object (one you need to validate, User in your case) with annotations from javax.validation.constraints package https://docs.oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html 使用来自javax.validation.constraints package https://docs.oracle.com/javaee/7/api/javax/validation/constraints/package的注释来注释域对象(您需要验证的域,需要验证的用户)的javax.validation.constraints package -summary.html

To perform validation ,you need to obtain instance of javax.validation.Validator and use it. 要执行验证,您需要获取javax.validation.Validator的实例并使用它。

Sample code 样例代码

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

It requires Spring Framework. 它需要Spring框架。 Note that constructing LocalValidatorFactoryBean is costly process. 请注意,构造LocalValidatorFactoryBean是昂贵的过程。

Generally, LocalValidatorFactoryBean should be constructed once, at application startup. 通常, LocalValidatorFactoryBean应该在应用程序启动时构造一次。

javax.xml.validation.Validator should be @Autowired where needed. 需要时,应将javax.xml.validation.Validator@Autowired

Spring Framework+Spring Boot will manage all those details for you. Spring Framework + Spring Boot将为您管理所有这些详细信息。

It is also possible to use java validation without Spring. 不使用Spring也可以使用Java验证。 Mandatory component is Validation Provider (JDK defines just interfaces, no implementation). 强制组件是验证提供程序(JDK仅定义接口,没有实现)。 Hibernate Validator is sample validation provider. Hibernate Validator是示例验证提供程序。

In this approach, you can perform your validation only in Spring-managed classes (services, controllers, etc). 在这种方法中,您只能在Spring托管的类(服务,控制器等)中执行验证。

This is not feasible solution for validating in constructor, in static methods. 这不是在静态方法中用于构造函数验证的可行解决方案。

Guava preconditions 番石榴先决条件

I used that when I was in need to perform validation from constructor. 当我需要从构造函数执行验证时,我曾用过它。

See Preconditions from Guava library https://github.com/google/guava/wiki/PreconditionsExplained 请参阅Guava库中的前提条件https://github.com/google/guava/wiki/PreconditionsExplained

It exposes functions like 它暴露了像

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

You could validate arguments in setters, constructor, build() method in your builders- every time where object building is finished and invariants need to be checked. 您可以在构建器中的setter,constructor,build()方法中验证参数,每次完成对象构建并需要检查不变量时。

In this scenario just Guava Library is required. 在这种情况下,仅需要Guava库。 It is not related to Java Validation API or implementation. 它与Java Validation API或实现无关。

Conditional validation 条件验证

If you want your validation to depend on the context (not just on the class you are validating) then validation rules shoud not be placed on the class you are validating. 如果您希望验证依赖于上下文(而不仅是您要验证的类),那么验证规则不应放在您要验证的类上。

In Spring you could write Validator as external class. 在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");
        }
    }
}

See http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#validator for more details. 有关更多详细信息,请参见http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#validator

Same principle (external class with validation logic) could be applied for Guava. 相同的原理(具有验证逻辑的外部类)可以应用于番石榴。

Then in your business logic you will be able to choose and use correct Validator. 然后,在您的业务逻辑中,您将能够选择并使用正确的验证器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM