Валидация через "миксин" - PullRequest
0 голосов
/ 11 декабря 2018

Я разрабатываю RESTful API в Spring Boot 2+, для которого мне нужно выполнить несколько проверок.Ничего особенного, только типичные @NotNull, @NotEmpty, @Max, @Min, @Email, @Regex, @Future и т. Д. ...

За исключением того, что у меня естьbean-компоненты из API, которые я должен использовать, но не могу изменить .Это означает, что я не могу комментировать поля и методы в этих DTO.

Было бы здорово, если бы я мог создать mixin-like классы или интерфейсы с такой же структурой реальных DTO, которые я должениспользовать в API, на котором я бы с удовольствием разместил аннотации bean-validation.

Например, если бы у меня были следующие DTO, которые я не мог бы изменить:

public class Person {
    private String name;
    private String dateOfBirth;
    private Address address;

    // constructors, getters and setters ommited
}

public class Address {
    private String street;
    private String number;
    private String zipCode;

    // constructors, getters and setters ommited
}

я бы создалследующие 2 интерфейса, которые имитируют их структуру и комментируют их по мере необходимости:

public interface PersonMixin {
    @NotBlank String name();
    @Past String dateOfBirth();
    @Valid @NotNull Address address();
}

public interface AddressMixin {
    @NotBlank String street();
    @Positive int number();
    @NotBlank String zipCode(); // Or maybe a custom validator
}

Как видите, имена методов в интерфейсах соответствуют именам свойств классов бинов.Это всего лишь одно возможное соглашение ...

Тогда, в идеале, где-нибудь, пока приложение загружается (обычно какой-то бин @Configuration), я был бы очень рад сделать что-то вроде:

ValidationMixinsSetup.addMixinFor(Person.class, PersonMixin.class);
ValidationMixinsSetup.addMixinFor(Address.class, AddressMixin.class);

За исключением того, что ValidationMixinsSetup.addMixinFor является чистой фантазией, то есть его не существует.

Я знаю, что существует аналогичная конструкция для Джексона в отношении сериализации / десериализации JSON.Я нашел это чрезвычайно полезным много раз.

Теперь я изучал исходный код Spring и Hibernate Validator.Но это не просто пирог ... Я копался в реализациях ValidatorFactory, LocalValidatorFactoryBean, TraversableResolver, но я не смог даже начать проверку концепции.Может ли кто-нибудь пролить свет на это?Т.е. не как реализовать весь функционал, а просто как и с чего начать.Мне нужны некоторые подсказки, касающиеся того, какие основные классы или интерфейсы нужно расширять и / или реализовывать, какие методы переопределять и т. Д.


РЕДАКТИРОВАТЬ 1: Может быть, этот подходне самый лучший.Если вы думаете, что есть лучший подход, пожалуйста, дайте мне знать.


РЕДАКТИРОВАТЬ 2: Что касается этого подхода, слишком сложного, слишком запутанного, Rube Goldberg ,и т.д., я ценю и уважаю эти точки зрения, но я не спрашиваю, хороша или плоха валидация с помощью миксинов, удобна или неудобна, а также почему это не так.Валидация с помощью mixins имеет свои плюсы сама по себе, и я думаю, что это может быть хорошим подходом для некоторых допустимых вариантов использования, т. Е. Иметь декларативную валидацию вместо скриптовой или программной валидации, в то же время отделяя валидацию от модели, позволяя базовой структуре выполнять фактическую работу валидации.пока я указываю только ограничения и т. д.

1 Ответ

0 голосов
/ 11 декабря 2018

Используя программный API (как упомянуто в комментарии), в случае Person вы можете применить следующие сопоставления для ваших ограничений:

    HibernateValidatorConfiguration config = Validation.byProvider( HibernateValidator.class ).configure();
    ConstraintMapping mapping = config.createConstraintMapping();
    mapping.type( Person.class )
            .field( "name" )
                .constraint( new NotNullDef() )
            .field( "number" )
                .constraint( new PositiveDef() )
            .field( "address" )
                .constraint( new NotNullDef() )
                .valid();

    Validator validator = config.addMapping( mapping )
            .buildValidatorFactory()
            .getValidator();

И, как вы используете Spring - вы бынужно сделать это в одном из ваших конфигурационных файлов sping, где вы определяете bean-компонент validator.

...