Проверка Spring REST для пользовательской аннотации

Я пытаюсь добавить дополнительную логику проверки в свои компоненты REST с помощью аннотаций. Это всего лишь пример, но дело в том, что аннотация должна использоваться для нескольких объектов ресурсов REST/DTO.

Я надеялся на такое решение:

public class Entity {

    @NotNull // JSR-303
    private String name;

    @Phone // Custom phonenumber that has to exist in a database
    private String phoneNumber;
}

@Component
public class PhoneNumberValidator implements Validator { // Spring Validator

    @Autowired
    private PhoneRepository repository;

    public boolean supports(Class<?> clazz) {
       return true;
    }

    public void validate(Object target, Errors errors) {
        Phone annotation = // find fields with annotations by iterating over target.getClass().getFields().getAnnotation
        Object fieldValue = // how do i do this? I can easily get the annotation, but now I wish to do a call to repository checking if the field value exists.
    }
}

person LG87    schedule 28.05.2016    source источник


Ответы (2)


Вы пробовали реализации валидатора JSR 303 bean, такие как валидатор гибернации, например. доступен здесь http://www.codejava.net/frameworks/spring/spring-mvc-form-validation-example-with-bean-validation-api

person Gibu George    schedule 28.05.2016
comment
Да, насколько я понял, я не могу использовать управляемые компоненты Spring при использовании способа JSR-303. Например. внедрить репозиторий в валидатор - person LG87; 28.05.2016
comment
Вы можете, аннотации должны быть добавлены к DTO, который вы хотите проверить, посмотрите на пример. - person Gibu George; 28.05.2016
comment
В примере не предусмотрены пользовательские аннотации. Насколько я вижу, для проверки используются только аннотации JSR-303. Но если вы хотите создать дополнительные аннотации, вы можете это сделать, но тогда вы создадите валидатор JSR-303, а не валидатор Spring. Пример: goldenpackagebyanuj.blogspot.no/2013/ 05/ Но что мне делать, если я хочу внедрить репозиторий в этот пользовательский ConstraintValidator? - person LG87; 28.05.2016
comment
Только что нашел это: stackoverflow.com/questions/ 21338883/, но все же не совсем то, что я ищу, так как модули maven разделены. Например: аннотации расположены в очень маленьком пакете, который используется совместно с другими проектами, но с помощью @Constraint(validatedBy=) мне нужно включить гораздо больше в этот пакет, контекст события Spring и репозиторий. - person LG87; 28.05.2016
comment
Другими словами, я хочу создать аннотации проверки, которые не имеют ограничения @, указывающего на реализацию. Причина в том, что открыты ресурсы maven, которые также используют другие проекты. Я предполагаю, что одним из решений будет использование @ Constraint, но затем установка другого модуля, как предусмотрено в maven, и только включение его на сервер. - person LG87; 28.05.2016

Модуль Maven А:

public interface RestValidator<A extends Annotation, T> extends ConstraintValidator<A, T>
public interface PhoneValidator extends RestValidator<PhoneNumber, String>

@Target(FIELD)
@Retention(RUNTIME)
@Constraint(validatedBy = PhoneValidator.class) // This usually doesnt work since its a interface
public @interface PhoneNumber {
   // JSR-303 required fields (payload, message, group)
}


public class Person {

@PhoneNumber
    private String phoneNumber;
}

Модуль Maven B:

@Bean
LocalValidatorFactoryBean configurationPropertiesValidator(ApplicationContext context, AutowireCapableBeanFactory factory) {
    LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
    factoryBean.setConstraintValidatorFactory(factory(context, factory));
    return factoryBean;
}

private ConstraintValidatorFactory factory(final ApplicationContext context, final AutowireCapableBeanFactory factory) {
    return new ConstraintValidatorFactory() {
        @Override
        public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
            if (RestValidator.class.isAssignableFrom(key)) {
                return context.getBean(key);
            } else {
                return factory.createBean(key);
            }
        }

        @Override
        public void releaseInstance(ConstraintValidator<?, ?> instance) {
            if (!(instance instanceof RestValidator<?, ?>)) {
                factory.destroyBean(instance);
            }
        }
    };
}

@Bean
WebMvcConfigurerAdapter webMvcConfigurerAdapter(final LocalValidatorFactoryBean validatorFactoryBean) {
    return new WebMvcConfigurerAdapter() {  // Adds the validator to MVC
        @Override
        public Validator getValidator() {
            return validatorFactoryBean;
        }
    };
}

Затем у меня есть реализация @Component PhoneValidator с Scope = Prototype.

Я ненавижу это решение, и я думаю, что Spring ДОЛЖЕН искать реализации интерфейса по умолчанию, но я уверен, что некоторые люди, которые намного умнее меня, приняли решение не делать этого.

person LG87    schedule 30.05.2016