0

我正在尝试使用注释在我的 REST bean 上添加一些额外的验证逻辑。这只是一个示例,但重点是注释将用于多个 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.
    }
}
4

2 回答 2

0

您是否尝试过 JSR 303 bean 验证器实现,例如 hibernate 验证器,例如可在此处获得http://www.codejava.net/frameworks/spring/spring-mvc-form-validation-example-with-bean-validation-api

于 2016-05-28T14:55:09.357 回答
0

Maven 模块 A:

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;
        }
    };
}

然后我有一个具有Scope = Prototype 的PhoneValidator 的@Component 实现。

我讨厌这个解决方案,我认为 Spring 应该默认查找接口实现,但我敢肯定,一些比我聪明得多的人决定不这样做。

于 2016-05-30T11:17:28.197 回答