【问题标题】:Javax Validation ImplementationJavax 验证实现
【发布时间】:2016-04-07 13:23:30
【问题描述】:

我正在尝试为局部变量创建自定义注释,但我只是不明白像 @NotNull@Null 这样的注释实际上是如何在代码中实现的。我查看了实际文件,这里是@NotNull

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = { })
public @interface NotNull {

    String message() default "{ javax.validation.constraints.NotNull.message }";

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

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

    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
    @Retention(RUNTIME)
    @Documented
    @interface List {
        NotNull[] value();
    }
}

但我看不到任何地方检查某物是否为null实际检查发生在哪里?

【问题讨论】:

    标签: java validation annotations


    【解决方案1】:

    通常需要提供用于验证的validateBy类

    @Target(TYPE)
    @Retention(RUNTIME)
    @Documented
    @Constraint(validatedBy = {TicketPresenceValidator.class})
    public @interface AtLeastOneTicket {
    }
    
    
    public class TicketPresenceValidator implements ConstraintValidator<AtLeastOneTicket, TicketInfo> {
     @Override
     public void initialize(TicketInfo constraintAnnotation) {
     }
    
     @Override
     public boolean isValid(TicketInfo ticketInfo, 
                            ConstraintValidatorContext context) {
        return ticketInfo.getSize() != 0;
     }
    }
    

    对于内置约束(来自 javax.validation.* 包),例如 NotNull 验证器由实现库提供。例如 Hibernate Validator 实现,这里是

    NullValidator 实现

    然后约束和验证器在helper class中链接在一起

    【讨论】:

    • 是的,我明白了那部分,我实际上做了一个使用该验证器的自定义注释。但我想知道@NotNull 是如何具体实现的,因为我在任何地方都看不到任何验证器。
    • 更新了答案,解释了内置约束。
    【解决方案2】:

    实际检查发生在哪里?

    如果您仔细查看 - javax.validation.constraints.@NotNull 源代码(您已粘贴),@Constraint(validatedBy = { }) 留空,即未指定哪个是实现类。这是因为 javax 验证 jar 像 - validation-api-2.0.1.Final.jar 等基本上是一个 bean 验证标准(一组没有实现的接口、注释等)。这些约束的实现由 hibernate、Oracle 等供应商提供。

    This link 列出了三个标准,因此您应该知道您使用的是哪个版本的 bean 验证标准。

    所以如果你有像 - hibernate-validator-6.0.10.Final.jar 这样的实现 jar,你也可以看到实现源代码,

    /*
     * Hibernate Validator, declare and validate application constraints
     *
     * License: Apache License, Version 2.0
     * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
     */
    package org.hibernate.validator.internal.constraintvalidators.bv;
    
    import javax.validation.ConstraintValidator;
    import javax.validation.ConstraintValidatorContext;
    import javax.validation.constraints.NotNull;
    
    /**
     * Validate that the object is not {@code null}.
     *
     * @author Emmanuel Bernard
     */
    public class NotNullValidator implements ConstraintValidator<NotNull, Object> {
    
        @Override
        public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {
            return object != null;
        }
    }
    

    现在,您必须了解搜索/解决 bean 验证标准的实现是一项复杂的任务,请参阅 - javax.validation.ValidationProviderResolver & 如果开发人员使用 Spring Boot 等框架,此过程会变得很容易。

    Answer by inigo skimmer 也做了这两件事 - 为您的自定义验证声明一个注释,实现实际验证并通过硬编码验证器类解析验证器 - @Constraint(validatedBy = {TicketPresenceValidator.class}) & 这使您免于复杂的验证实现搜索逻辑。

    您必须了解的另一部分是您的验证器类型为javax.validation.ConstraintValidator,因此请阅读 javadoc 作为您需要提供给this interface 的内容

    其他可以参考的链接,

    Creating custom constraints

    Create Your Own Constraints With Bean Validation 2.0

    【讨论】:

      猜你喜欢
      • 2011-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-04
      • 1970-01-01
      • 2018-06-20
      相关资源
      最近更新 更多