使用 dropwizard 验证,我可以访问数据库以插入记录吗

With dropwizard validation, can I access the DB to insert a record

我的问题如下:

我正在为一个项目使用dropwizard,到目前为止,我已经愉快而成功地使用了验证框架。我的验证工作正常,并且以标准方式使用。这是我的:

请求class:

import javax.validation.constraints.NotNull;

import MandatoryFieldLengthCheck;

public class InitiatePaymentRequest implements PaymentRequest {

    @NotNull(message = "Mandatory input field missing")
    @MandatoryFieldLengthCheck(value = 32)
    protected String   transactionId;
}

然后注解class:

@Target({ METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = MandatoryFieldLengthCheckValidator.class)
@Documented
public @interface MandatoryFieldLengthCheck {

    String message() default "Invalid input data";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    long value();

}

然后验证者class:

public class MandatoryFieldLengthCheckValidator implements ConstraintValidator<MandatoryFieldLengthCheck, Object> {

    private static final Logger LOGGER = LoggerFactory.getLogger(MandatoryFieldLengthCheckValidator.class);

    private long                length;

    @Override
    public void initialize(final MandatoryFieldLengthCheck constraintAnnotation) {
        this.length = constraintAnnotation.value();
    }

    @Override
    public boolean isValid(final Object object, final ConstraintValidatorContext constraintContext) {
        LOGGER.debug("isValid [{}]", object);

        // fields with a MandatoryFieldLengthCheck will also have a NotNull annotation so
        // nulls will be handled there, to avoid returning an invalid field value return true here
        if (object == null) {
            return true;
        }

        if (object instanceof Long || object instanceof Integer || object instanceof Short) {
            return object.toString().length() <= this.length;
        } else if (object instanceof String) {
            return (((String) object).replace(" ", "").length() > 0) && (((String) object).length() <= this.length);
        } else {
            return false;
        }
    }
}

这是有效的,很好。

现在,从 MandatoryFieldLengthCheckValidator 中,我想在数据库中插入一条记录(它必须是数据库),例如出于审计目的验证失败。

我尝试注入 DAO 但没有成功,不确定是否可行。验证器是即时创建的,所以我无法控制我通过或不通过的内容,除非有一些魔法注入 dao。

所以我的问题是我该怎么做,更具体地说:

即使你不完全正确,如果你指出我正确的方向,它会很感激。谢谢

soz,我来晚了。也有一种方法可以让它工作(注入验证器)。请注意,验证器应该简单的评论仍然适用,但有时您只需要注入一些其他对象即可进行正确验证。因此,这就是实现此目标的方法:

首先,我假设您已经设置了 DI。如果没有,请查看 https://github.com/xvik/dropwizard-guicey - 它将 guice 集成到 dropwizard 中并且也做得很好。一旦你完成了这个设置,你就快完成了。

Validation 在 Validator class 上运行,它将动态创建您的验证器 - 你是对的。此创建将无法注入任何值,因为它并不是开箱即用的。

您可以创建一个模块(由 guice 处理)来为您创建验证器。这看起来像这样:

public class ValidationModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(GuiceConstraintValidationFactory.class).in(Singleton.class);
    }

    @Provides
    public Validator validator(GuiceConstraintValidationFactory validatoFactory) {
        return Validation.byDefaultProvider().configure().constraintValidatorFactory(validatoFactory).buildValidatorFactory().getValidator();
    }

}

请注意,这将创建一个 GuiceConstraintValidationFactory。这个工厂只是一个委托,它将 return 正确的验证器。它是一个委托,因此旧的验证器仍然有效(NotNull 和朋友)。这是一些代码:

public class GuiceConstraintValidationFactory implements ConstraintValidatorFactory {

    private ConstraintValidatorFactory delegate;
    private Set<ConstraintValidator> validators;

    @Inject
    public GuiceConstraintValidationFactory(final Set<ConstraintValidator> validators) {
        this.validators = validators;
        delegate = new ConstraintValidatorFactoryImpl();
    }

    @Override
    public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
        for(ConstraintValidator<?, ?> validator : validators) {
            if(validator.getClass() == key) {
                return (T) validator;
            }
        }
        return delegate.getInstance(key);
    }

    @Override
    public void releaseInstance(ConstraintValidator<?, ?> instance) {
        delegate.releaseInstance(instance);
    }

}

注意这个 class 是如何注入验证器的。这些验证器是 guice 句柄,因此它们可以注入字段。例如:

@Plugin(ConstraintValidator.class)
public class ResourceValidator implements ConstraintValidator<ValidResource, String>{


    private static final Logger log = Logger.getLogger(ResourceValidator.class);

    @Inject
    private MyConfiguration conf;

    @Override
    public void initialize(ValidResource constraintAnnotation) {
        // nothing to do here
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if(value == null) {
            return true;
        }
        String fullPath = conf.getBasePath() + File.separator + value;
        return new File(fullPath).exists();
    }

}

这个验证器是 guice 处理的。 @Plugin 注释使 guicey dropwizard 能够创建实例,注入它,然后将所有实例分组到一个集合中(使注入它们更容易)参见 GuiceConstraintValidationFactory,其中将一组验证器注入工厂。 这个工厂现在将被默认的验证器使用。当请求一个新的验证器时,工厂检查是否存在所需类型的 guice 管理的验证器。如果不是,它将默认返回到正常的验证器实现。如果是,它将 return guice 管理的验证器。这使您能够动态添加新的验证器,并让 guice 创建、管理和注入它们。

希望对您有所帮助。

-- 阿图尔