使用 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。
所以我的问题是我该怎么做,更具体地说:
- 我可以注入 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 创建、管理和注入它们。
希望对您有所帮助。
-- 阿图尔
我的问题如下:
我正在为一个项目使用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。
所以我的问题是我该怎么做,更具体地说:
- 我可以注入 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 创建、管理和注入它们。
希望对您有所帮助。
-- 阿图尔