java - javax.validation.UnexpectedTypeException 使用 Spring ConstraintValidator 进行枚举
问题描述
我已经实现了一个 ConstraintValidator 以验证包含枚举的 DTO。为此,我遵循了这个 Spring 文档。
这是要应用于枚举字段的自定义注释:
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR,
ElementType.ANNOTATION_TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumValidator.class)
public @interface ValidEnum {
String message() default "{com.test.validation.constraints.ValidEnum}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
Class<? extends Enum<?>> target();
}
EnumValidator
看起来像这样:
public class EnumValidator implements ConstraintValidator<ValidEnum,String> {
private Set<String> enumValues;
@Override
public void initialize(ValidEnum targetEnum) {
Class<? extends Enum> enumSelected = targetEnum.targetClassType();
enumValues = (Set<String>) EnumSet.allOf(enumSelected).stream()
.map(e -> ((Enum<? extends Enum<?>>) e).name()).collect(Collectors
.toSet());
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return enumValues.contains(value);
}
}
这是枚举:
public enum Gender {
MALE,FEMALE;
}
这是要验证的 DTO:
public final class UserDTO{
@ValidEnum(target = Gender.class)
private Gender gender;
@NotEmpty
@Max(100)
private String fullName;
}
以及验证字段的控制器:
@Controller
public class RegistrationController {
private static final String REGISTER_USER = "/register";
private final RegistrationService registrationService;
@PostMapping(value = REGISTER_USER)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public UserRegistrationResponse register(@Valid UserDTO userRegistrationRequest) {
return registrationService.register(userRegistrationRequest);
}
}
似乎 Spring 没有检测到验证器,因为它抛出了这个异常:
org.springframework.web.util.NestedServletException: Request processing failed;
nested exception is javax.validation.UnexpectedTypeException: HV000030:
No validator could be found for constraint 'com.test.ws.web.validation.ValidEnumType' validating type 'com.test.ws.domain.model.Gender'. Check configuration for 'gender'
我正在使用 Spring boot 2.0.4,其中包含验证所需的依赖项。
知道为什么会失败吗?
解决方案
您的代码中有三个错误。
@Max(100)
此注释不应应用于字符串字段!仅适用于数字类型。如果您需要指定字符串大小范围限制,您可以使用@Size(min = 2, max = 250)
注释。- 您忘记
RequestBody
了控制器方法签名中的注释:
register(@Valid @RequestBody UserDTO userRegistrationRequest)
- 枚举验证使用来自 Rest API 的字符串值,而不是 Enum 本身。这就是为什么你在这里有一个错误。
我已经为你创建了测试项目。请在此处查看https://github.com/alex-petrov81/stackoverflow-answers/tree/master/enum-validator
推荐阅读
- python - Python Web Scraper 问题
- replace - 如何通过在 mongodb 中运行单个查询来替换所有文档中的 profilepic url 路径的一小部分
- angular - 带有状态管理的 Angular 新窗口
- swift - Swift 中的预期声明
- kubernetes - Kubernetes pod desc 显示“连接被拒绝”错误
- java - 升级到 WL 12C 和 Java 1.8 后的 JAVA 时间相关挑战
- reactjs - Codesandbox.io React 项目中的代理“localhost”
- java - 需要代理身份验证,改造
- neo4j - neo4j的父节点实体中如何查询子节点?
- python - 需要知道访问我的回复表的方式吗?