11

在我们的项目中,我们在单独的 Maven 模块中有服务和 DAO 层。服务模块依赖于 DAO 模块并与它的实体一起工作。问题是我们不能放置自定义 jsr 303 约束,它使用 DAO 实体中服务层的一些服务,因为这会创建从 DAO 层到服务层的反向引用,因为验证器类需要在自定义的验证属性中引用@约束。

有没有办法(使用标准 jsr 303 api)在运行时指定一些自定义约束的验证器类(或以任何其他方式解决我们的问题)?内置约束有空的validateBy属性,但我不知道是否有一些API。

4

2 回答 2

13

我们在基于 Spring 的项目中遇到了同样的问题。为了以最好的 Spring 方式解决它,我们拆分了 ConstraintValidator 接口和实现。例如在领域层我们只有接口:

public interface UniqueValidator extends ConstraintValidator<Unique, String> {
}

在服务层中,我们实现了该接口:

public class UniqueValidatorJpaImpl implements UniqueValidator {
    private EntityManager entityManager;
    ...
}

接下来我们在 Spring Context 中为 UniqueValidatorJpaImpl 声明一个 bean。

最后,为了让所有员工都能正常工作,我们扩展了 SpringConstraintValidatorFactory。默认情况下,它只创建在validateBy中指定的类的新实例。我们通过首先在 spring 上下文中查找相应类型的 bean 来扩展它:

public class SpringConstraintValidatorFactoryEx implements ConstraintValidatorFactory {

    private final Logger logger = LoggerFactory.getLogger(SpringConstraintValidatorFactoryEx.class);

    @Autowired
    private AutowireCapableBeanFactory beanFactory;

    public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
        T bean = null;

        try {
            logger.info("Trying to find a validator bean of class " + key.getSimpleName());
            bean = this.beanFactory.getBean(key);
        } catch (BeansException exc) {
            logger.info("Failed to find a bean of class " + key.getSimpleName());
        }

        if (bean == null) {
            try {
                logger.info("Creating a new validator bean of class " + key.getSimpleName());
                bean = this.beanFactory.createBean(key);
            } catch (BeansException exc) {
                logger.info("Failed to create a validator of class " + key.getSimpleName());
            }
        }

        if (bean == null) {
            logger.warn("Failed to get validator of class " + key.getSimpleName());
        }

        return bean;
    }

}
于 2013-08-21T08:43:34.277 回答
5

您可以使用基于XML 的约束映射来为您的约束分配验证器,以避免从注释引用到验证器实现。

BV 1.1 EG也在讨论该领域的一些改进。随意权衡邮件列表上的问题。

于 2012-07-30T19:00:17.937 回答