java - 包装列表的自定义验证抛出 UnexpectedTypeException: HV000030
问题描述
我一直对在对象列表上使用的自定义验证器感到头疼。该示例是借用代码,但使用包装类 ValidList 来嵌入实际列表。现在,当我使用像 Size(min=1) 这样的 ootb 注释时,验证有效。但是,如果我使用自定义注释(不要查看功能,这里仅用于演示),我会收到一个 500 错误,带有臭名昭著的 HV000030:
No validator could be found for constraint 'com.example.demo.validation.ListLength' validating type 'java.util.List<SomePojo>'. Check configuration for 'list'
当我打电话时
$ curl -H 'Content-Type: application/json' -X POST -d '[{"id":1,"token":"lalala"}]' http://localhost:8080/pojos
(我使用 Lombok 的 @Value 来实现 getter/setter 和不变性)
有谁知道怎么回事?
@RestController
public class SomeController {
@PostMapping("/pojos")
public ValidList<SomePojo> test(@Valid @RequestBody ValidList<SomePojo> pojos) {
return pojos;
}
}
@Value
public class ValidList<SomePojo> {
@JsonValue
@ListLength
//@Size(min=1)
private List<SomePojo> values;
@JsonCreator
public ValidList(SomePojo... items) {
this.values = Arrays.asList(items);
}
}
@Value
public class SomePojo {
int id;
String token;
}
@Documented
@Constraint(validatedBy = ListValidator.class)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface ListLength {
String message() default "Not enough pojos";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface List {
ListLength[] value();
}
}
public class ListValidator implements ConstraintValidator<ListLength, List<SomePojo>> {
@Override
public boolean isValid(List<SomePojo> somePojos, ConstraintValidatorContext constraintValidatorContext) {
return somePojos.size() > 1;
}
}
解决方案
该异常的原因是在定义中SomePojo
用作通用参数。您应该在实现中对泛型类型使用通配符。List
ListValidator
ConstraintValidator
从javadoc复制:
实现必须遵守以下限制:
T
必须解析为非参数化类型- 或泛型参数
T
必须是无界通配符类型
所以你应该这样重写ListValidator
:
public class ListValidator implements ConstraintValidator<ListLength, List<?>> {
@Override
public boolean isValid(List<?> somePojos, ConstraintValidatorContext constraintValidatorContext) {
return somePojos.size() > 1;
}
}
有关更多信息,请查看ConstraintValidator
javadoc和Bean 验证文档。
推荐阅读
- json - 在按钮单击时更改特定项目的值
- sql - 在 sql 中 PIVOT 下表
- javascript - 如何从 React.FormEvent 中检索表单值
? - android - 如何减小 android 本机共享库(.so 文件)的大小?
- java - 如何仅使用本地目录作为存储库在 gradle 上设置 springframework?
- python - Matplotlib df.plot() 显示点而不是线,即使指定
- mysql - 如何使用 mySQL 语法将 UNIQUE 字段添加到包含我的表的数据的现有表
- php - PHP CURL - 当你只知道 id 时抓取 seo url
- javascript - 当我只想传递一个字符串(ANGULAR 5 AND FIREBASE)时,角度反应形式制作对象
- python - 使用python查找集群