как добавить собственный валидатор для аннотации javax.validation.constraints?

Я реализовал проверку для поля Long и проверки @PastOrPresent

public class PastOrPresentValidator implements ConstraintValidator<PastOrPresent, Long>{
    @Override
    public boolean isValid(Long value, ConstraintValidatorContext context) {
        if (value == null) {
            return false;
        }
        return value <= System.currentTimeMillis();
    }
}

public class MyDto {
    @PastOrPresent
    Long timestamp;    
}

И получил ошибку:

HV000030: No validator could be found for constraint 'javax.validation.constraints.PastOrPresent' validating type 'java.lang.Long'. Check configuration for 'push.dto.timestamp'

Но когда я создаю пользовательскую аннотацию, например @PastOrPresentLong, и использую тот же код валидатора, все работает.

Есть ли способ добавить собственный валидатор для аннотации javax.validation.constraints?


person Cherry    schedule 21.02.2019    source источник
comment
Я думаю, вы должны принять этот замечательный ответ.   -  person Pavel_K    schedule 09.10.2020


Ответы (1)


Просто реализовать интерфейс ConstraintValidator недостаточно, чтобы ваш новый валидатор заработал. Его нужно как-то зарегистрировать, чтобы об этом знал провайдер BeanValidation. Это можно сделать с помощью XML (см. дополнительную информацию здесь):

<constraint-mappings
        xmlns="http://xmlns.jcp.org/xml/ns/validation/mapping"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/validation/mapping
            http://xmlns.jcp.org/xml/ns/validation/mapping/validation-mapping-2.0.xsd"
        version="2.0">
    <!-- anything else -->
    <constraint-definition annotation="javax.validation.constraints.PastOrPresent">
        <validated-by include-existing-validators="true">
            <value>org.mycompany.PastOrPresentLongValidator</value>
        </validated-by>
    </constraint-definition>
</constraint-mappings>

Затем, если вы используете Hibernate Validator в качестве поставщика BeanValidation, у вас также есть еще два варианта — использовать загрузчик службы или программное определение. Использование Service loader — самый простой способ добавления нового валидатора. Все, что вам нужно сделать, это создать файл META-INF/services/javax.validation.ConstraintValidator и добавить в него FQCN вашего валидатора. См. подробные примеры в этом опубликовать в разделе "Использование стандартных ограничений для нестандартных классов" или в документ. С программным подходом вам нужно было бы сделать что-то вроде:

ConstraintMapping constraintMapping = configuration.createConstraintMapping();

constraintMapping
        .constraintDefinition( PastOrPresent.class )
        .validatedBy( PastOrPresentLongValidator.class );

А затем добавьте это сопоставление ограничений в свою конфигурацию и создайте из него валидатор:

Validator validator = configuration.addMapping( constraintMapping )
        .buildValidatorFactory()
        .getValidator();

Но, как я упоминал ранее, Service Loader — это самый простой и быстрый способ.

person mark_o    schedule 22.02.2019