【问题标题】:Spring REST validation on custom annotation自定义注释上的 Spring REST 验证
【发布时间】:2016-09-26 18:53:45
【问题描述】:

我正在尝试使用注释在我的 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.
    }
}

【问题讨论】:

    标签: java spring validation spring-mvc jsr


    【解决方案1】:

    您是否尝试过 JSR 303 bean 验证器实现,例如休眠验证器 例如可以在这里找到http://www.codejava.net/frameworks/spring/spring-mvc-form-validation-example-with-bean-validation-api

    【讨论】:

    • 是的,据我了解,在使用 JSR-303 方式时,我无法使用 Spring 托管 bean。例如。将存储库注入验证器
    • 可以,注解要加在要验证的DTO上,看例子。
    • 示例不提供自定义注解。据我所知,它只使用 JSR-303 注释进行验证。但是如果你想创建额外的注释,你可以这样做,但是你将创建一个 JSR-303 验证器,而不是 Spring 验证器。示例:goldenpackagebyanuj.blogspot.no/2013/05/… 但是,如果我希望将存储库注入到该自定义 ConstraintValidator 中,我该怎么做?
    • 刚发现这个:stackoverflow.com/questions/21338883/… 但仍然不是我要找的,因为 Maven 模块是分开的。例如:注释位于一个在其他项目之间共享的非常小的包中,但是使用 @Constraint(validatedBy=) 我必须在该包、事件 Spring 上下文和存储库中包含更多内容。
    • 另一种说法,我希望创建验证注释,它没有指向实现的@Constraint。原因是暴露了其他项目也使用的 Maven 资源。我想一个解决方案是使用@Constraint,然后设置另一个模块,如 maven 中提供的那样,并且只包含服务器端。
    【解决方案2】:

    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 应该默认查找接口实现,但我敢肯定一些比我聪明得多的人决定不这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-14
      • 2018-06-08
      • 2014-09-24
      • 2017-03-06
      • 1970-01-01
      相关资源
      最近更新 更多