Dropwizard 和验证对象列表
Dropwizard and validating lists of objects
我有一个 dropwizard 服务,它接受代表 bean 的 JSON 文档的 PUT。我在 bean 实现中使用约束注释,并在我的资源方法中使用 @Valid 注释:
@PUT
public Response write(@Valid MyBean bean);
一切正常。
但是现在,我想在 JSON 中传递一个 数组 对象。我只是将方法签名更改为
@PUT
public Response write(@Valid List<MyBean> beans);
它通常有效,但如果存在验证错误,则响应不是很友好。例如,如果我 post 在数组中的 100 个 beans 中,并且其中 一个 缺少一个 'name' 属性,那么响应是
{"errors":["name may not be empty"]}
没有任何指示请求中的哪个 bean 有问题。
有办法克服这个问题吗?
如果做不到这一点,我有没有办法在资源 class 中获得一个验证器,以便我自己处理所有这些?
您想要的方式可能无法实现。这是对正在发生的事情以及 Hibernate 希望您如何挂钩它的独立测试:
public class ListBeanValidationTest {
public static void main(String[] args) {
List<Bean> asList = Arrays.asList(new Bean("test"), new Bean("test2"));
Validator v = Validators.newConfiguration().messageInterpolator(new MsgInterpolator()).buildValidatorFactory().getValidator();
// this is what DW does but i am lazy so you get the main version
if(asList instanceof Iterable) {
Iterable values = (Iterable) asList;
Set<ConstraintViolation<Object>> violations = new HashSet<>();
for(Object value : values) {
violations.addAll(v.validate(value));
}
violations.forEach(System.out::println);
}
}
public static class Bean {
Bean(String name) {
this.name = name;
}
String name;
@NotEmpty(message="bean not empty ${name}")
String wrong;
}
public static class MsgInterpolator implements MessageInterpolator {
@Override
public String interpolate(String messageTemplate, Context context) {
return interpolate(messageTemplate, context, Locale.getDefault());
}
@Override
public String interpolate(String messageTemplate, Context context, Locale locale) {
Object validatedValue = context.getValidatedValue();
return null;
}
}
}
MessageInterpolator
是这里的问题。它在为您插入消息时没有 bean 的实例,因此遗憾的是您不能使用对它的引用。这意味着您将不得不以另一种方式执行此操作。
您可以获得对您的 validator
的引用(如何执行此操作取决于您,您可以在 DW 环境中找到它。为此我使用 DI via Guice
)。
如果您想以 DW 方式执行此操作,您可以考虑扩展:JacksonMessageBodyProvider
- 这是对 DW 资源进行验证的 class。
希望对你有帮助
您还可以在此处阅读可用的验证选项:https://docs.jboss.org/hibernate/validator/5.1/reference/en-US/html/chapter-message-interpolation.html#section-custom-message-interpolation
-- 阿图尔
我有一个 dropwizard 服务,它接受代表 bean 的 JSON 文档的 PUT。我在 bean 实现中使用约束注释,并在我的资源方法中使用 @Valid 注释:
@PUT
public Response write(@Valid MyBean bean);
一切正常。
但是现在,我想在 JSON 中传递一个 数组 对象。我只是将方法签名更改为
@PUT
public Response write(@Valid List<MyBean> beans);
它通常有效,但如果存在验证错误,则响应不是很友好。例如,如果我 post 在数组中的 100 个 beans 中,并且其中 一个 缺少一个 'name' 属性,那么响应是
{"errors":["name may not be empty"]}
没有任何指示请求中的哪个 bean 有问题。
有办法克服这个问题吗?
如果做不到这一点,我有没有办法在资源 class 中获得一个验证器,以便我自己处理所有这些?
您想要的方式可能无法实现。这是对正在发生的事情以及 Hibernate 希望您如何挂钩它的独立测试:
public class ListBeanValidationTest {
public static void main(String[] args) {
List<Bean> asList = Arrays.asList(new Bean("test"), new Bean("test2"));
Validator v = Validators.newConfiguration().messageInterpolator(new MsgInterpolator()).buildValidatorFactory().getValidator();
// this is what DW does but i am lazy so you get the main version
if(asList instanceof Iterable) {
Iterable values = (Iterable) asList;
Set<ConstraintViolation<Object>> violations = new HashSet<>();
for(Object value : values) {
violations.addAll(v.validate(value));
}
violations.forEach(System.out::println);
}
}
public static class Bean {
Bean(String name) {
this.name = name;
}
String name;
@NotEmpty(message="bean not empty ${name}")
String wrong;
}
public static class MsgInterpolator implements MessageInterpolator {
@Override
public String interpolate(String messageTemplate, Context context) {
return interpolate(messageTemplate, context, Locale.getDefault());
}
@Override
public String interpolate(String messageTemplate, Context context, Locale locale) {
Object validatedValue = context.getValidatedValue();
return null;
}
}
}
MessageInterpolator
是这里的问题。它在为您插入消息时没有 bean 的实例,因此遗憾的是您不能使用对它的引用。这意味着您将不得不以另一种方式执行此操作。
您可以获得对您的 validator
的引用(如何执行此操作取决于您,您可以在 DW 环境中找到它。为此我使用 DI via Guice
)。
如果您想以 DW 方式执行此操作,您可以考虑扩展:JacksonMessageBodyProvider
- 这是对 DW 资源进行验证的 class。
希望对你有帮助
您还可以在此处阅读可用的验证选项:https://docs.jboss.org/hibernate/validator/5.1/reference/en-US/html/chapter-message-interpolation.html#section-custom-message-interpolation
-- 阿图尔