使用 Spring ConstraintValidator 进行枚举的 javax.validation.UnexpectedTypeException

标签 java validation spring-boot spring-validator

我已经实现了 ConstraintValidator 来验证包含枚举的 DTO。我关注了this Spring documentation为此。

这是要应用于枚举字段的自定义注释:

@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 :

@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 似乎没有检测到 validator ,因为它抛出了这个异常:

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,其中包含验证所需的依赖项。

知道为什么失败吗?

最佳答案

您的代码中有三个错误。

  1. @Max(100) 此注释不应应用于字符串字段!仅适用于数字类型。如果需要指定字符串大小范围限制,可以使用 @Size(min = 2, max = 250) 注释。
  2. 您忘记了 Controller 方法签名中的 RequestBody 注释:

注册(@Valid @RequestBody UserDTO userRegistrationRequest)

  • 枚举验证使用来自 Rest API 的字符串值,而不是枚举本身。这就是你这里出错的原因。
  • 我已经为您创建了测试项目。请在这里查看https://github.com/alex-petrov81/stackoverflow-answers/tree/master/enum-validator

    关于使用 Spring ConstraintValidator 进行枚举的 javax.validation.UnexpectedTypeException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52127174/

    相关文章:

    java - 数组列表 java 错误

    validation - 由于重复的 "class"规范和单选按钮标签问题,站点将无法验证

    javascript - 是否可以为我站点上的所有 jQuery 验证使用站点范围的默认设置?

    java - Azure Webapp Java Rest API 端点不起作用

    java - Spring boot + Envers ClassNotFoundException

    java - 使用 org.json.simple json 解析器将变量从 while 循环传递到另一个类

    java - 你如何获得 JPanel 引入的边距

    java - 当我发送消息时,我可以在 firebase 中看到它,但我无法在模拟器或手机上读取它,它什么也没有显示

    c# - 注释验证不起作用

    java - JPA 标准规范 - 使用 group by 进行多选返回所有列