validation - 使用 Hibernate Validator (JSR 303) 进行跨领域验证

标签 validation hibernate-validator bean-validation

Hibernate Validator 4.x 中是否有跨字段验证的实现(或第三方实现)?如果没有,实现跨字段验证器的最简洁方法是什么?

举个例子,如何使用 API 来验证两个 bean 属性是否相等(例如验证密码字段与密码验证字段是否匹配)。

在注释中,我期望类似的内容:

public class MyBean {
  @Size(min=6, max=50)
  private String pass;

  @Equals(property="pass")
  private String passVerify;
}

最佳答案

每个字段约束应该由不同的验证器注释来处理,或者换句话说,不建议让一个字段的验证注释与其他字段进行检查;跨领域验证应该在类级别进行。此外,JSR-303 Section 2.2表达同一类型的多个验证的首选方法是通过注释列表。这允许在每次匹配时指定错误消息。

例如,验证通用表单:

@FieldMatch.List({
        @FieldMatch(first = "password", second = "confirmPassword", message = "The password fields must match"),
        @FieldMatch(first = "email", second = "confirmEmail", message = "The email fields must match")
})
public class UserRegistrationForm  {
    @NotNull
    @Size(min=8, max=25)
    private String password;

    @NotNull
    @Size(min=8, max=25)
    private String confirmPassword;

    @NotNull
    @Email
    private String email;

    @NotNull
    @Email
    private String confirmEmail;
}

注释:

package constraints;

import constraints.impl.FieldMatchValidator;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;

/**
 * Validation annotation to validate that 2 fields have the same value.
 * An array of fields and their matching confirmation fields can be supplied.
 *
 * Example, compare 1 pair of fields:
 * @FieldMatch(first = "password", second = "confirmPassword", message = "The password fields must match")
 * 
 * Example, compare more than 1 pair of fields:
 * @FieldMatch.List({
 *   @FieldMatch(first = "password", second = "confirmPassword", message = "The password fields must match"),
 *   @FieldMatch(first = "email", second = "confirmEmail", message = "The email fields must match")})
 */
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = FieldMatchValidator.class)
@Documented
public @interface FieldMatch
{
    String message() default "{constraints.fieldmatch}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    /**
     * @return The first field
     */
    String first();

    /**
     * @return The second field
     */
    String second();

    /**
     * Defines several <code>@FieldMatch</code> annotations on the same element
     *
     * @see FieldMatch
     */
    @Target({TYPE, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Documented
            @interface List
    {
        FieldMatch[] value();
    }
}

验证器:

package constraints.impl;

import constraints.FieldMatch;
import org.apache.commons.beanutils.BeanUtils;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object>
{
    private String firstFieldName;
    private String secondFieldName;

    @Override
    public void initialize(final FieldMatch constraintAnnotation)
    {
        firstFieldName = constraintAnnotation.first();
        secondFieldName = constraintAnnotation.second();
    }

    @Override
    public boolean isValid(final Object value, final ConstraintValidatorContext context)
    {
        try
        {
            final Object firstObj = BeanUtils.getProperty(value, firstFieldName);
            final Object secondObj = BeanUtils.getProperty(value, secondFieldName);

            return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
        }
        catch (final Exception ignore)
        {
            // ignore
        }
        return true;
    }
}

关于validation - 使用 Hibernate Validator (JSR 303) 进行跨领域验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1972933/

相关文章:

java - 为什么 session bean 方法在抛出 RuntimeException 时抛出 EjbTransactionRolledbackException

Kotlin 和 javax.validation.constraints.NotNull

validation - Backbone.js:在集合上运行验证并触发错误事件,但如果验证失败则不中止集合

javascript - jQuery:检查 href 属性是否有效的简单方法

java - hibernate validator : Only Return Child Name in Path for Property Paths

整数的 hibernate validator 列表

hibernate-validator - 导入org.hibernate.validator.ClassValidator无法解析

validation - WSO2 API Manager - token 限制 20KPerToken

python - 在 tkinter 中交互验证 Entry 小部件内容(第 2 部分 - 更改条目对象的属性)

hibernate - 如何使用 Hibernate 配置自定义消息插值?