找不到用于自定义注释的验证器和枚举Springboot Java8的验证

发布于 2025-01-20 05:11:38 字数 1498 浏览 0 评论 0原文

获取此错误HV000030:对于“ Myenum”的约束验证类型的Myenum检查配置,找不到验证器。

使用此类的注释要验证,我不能做私有最终字符串myenum,因为我需要将其用作枚举,以便在枚举

public class Request {
     @EnumChecker(enumclass = MyEnum.class)
     private final MyEnum myenum;
}

注释

@Documented
@Constraint(validatedBy = MyEnumValidator.class)
@Target({FIELD, PARAMETER, TYPE, TYPE_USE, TYPE_PARAMETER, METHOD, CONSTRUCTOR, ANNOTATION_TYPE})
@Retention(RUNTIME)
public @interface EnumChecker {
  String message() default "must be one of these values";
  Class<?>[] groups() default {};
  Class<? extends Payload>[] payload() default {};
  Class<? extends Enum> enumClass();
}

验证器

public class MyEnumValidator implements ConstraintValidator<EnumChecker, String> {
  private List<String> validEnumList;

  @Override
  public void initialize(EnumChecker constraintAnnotation) {
    validEnumList = Arrays.stream(constraintAnnotation.enumClass().getEnumConstants())
        .map(Enum::name)
        .collect(Collectors.toList());
  }

  @Override
  public boolean isValid(String value, ConstraintValidatorContext context) {
    return validEnumList.contains(value);
  }
}

枚举中使用该函数

public enum MyEnum {

  YES, NO;

  private static final Map<MyEnum, String> MyEnumConverter =
      Map.of(YES, "yes");

  public String toMyString() {
    return MyEnumConverter.get(this);
  }

}

Getting this error HV000030: No validator could be found for constraint EnumChecker validating type MyEnum Check configuration for ‘myenum’.

Using the annotation on this class to be validated, I can't do private final String myenum because I need to use it as an enum in order to use the function inside the enum

public class Request {
     @EnumChecker(enumclass = MyEnum.class)
     private final MyEnum myenum;
}

annotation

@Documented
@Constraint(validatedBy = MyEnumValidator.class)
@Target({FIELD, PARAMETER, TYPE, TYPE_USE, TYPE_PARAMETER, METHOD, CONSTRUCTOR, ANNOTATION_TYPE})
@Retention(RUNTIME)
public @interface EnumChecker {
  String message() default "must be one of these values";
  Class<?>[] groups() default {};
  Class<? extends Payload>[] payload() default {};
  Class<? extends Enum> enumClass();
}

validator

public class MyEnumValidator implements ConstraintValidator<EnumChecker, String> {
  private List<String> validEnumList;

  @Override
  public void initialize(EnumChecker constraintAnnotation) {
    validEnumList = Arrays.stream(constraintAnnotation.enumClass().getEnumConstants())
        .map(Enum::name)
        .collect(Collectors.toList());
  }

  @Override
  public boolean isValid(String value, ConstraintValidatorContext context) {
    return validEnumList.contains(value);
  }
}

enum

public enum MyEnum {

  YES, NO;

  private static final Map<MyEnum, String> MyEnumConverter =
      Map.of(YES, "yes");

  public String toMyString() {
    return MyEnumConverter.get(this);
  }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

や莫失莫忘 2025-01-27 05:11:38

首先删除 myenum 中的 final 修饰符,并为该字段创建 setter 和 getter,因为 Jackson 无法将 http 请求中的值绑定到您的 <例如 code>Request 类。

public class Request {
  @EnumChecker(enumClass = MyEnum.class)
  private MyEnum myenum;
  
  public MyEnum getMyenum() {
    return myenum;
  }
  
  public void setMyenum(MyEnum myenum) {
    this.myenum = myenum;
  }
}

然后更改 ConstraintValidator 目标类型以匹配 MyEnum 而不是 String

public class MyEnumValidator implements ConstraintValidator<EnumChecker, MyEnum> {

  private List<MyEnum> validEnumList;

  @Override
  public void initialize(EnumChecker constraintAnnotation) {
    validEnumList = Arrays.stream(constraintAnnotation.enumClass().getEnumConstants())
        .collect(Collectors.toList());
  }
  @Override
  public boolean isValid(MyEnum value, ConstraintValidatorContext context) {
    return validEnumList.contains(value);
  }
}

测试:我做了以下测试

@RestController
public class MainController {

  @PostMapping("/annot")
  public String filter(@RequestBody @Valid Request req) {
    return req.getMyenum().name();
  }
}

我还更改了实现 MyEnumValidator 仅查看验证效果并证明其发生。 (我承认目前这个验证器没有意义。同时使用 only @RequestBody 保证 myenum 只能有 YES 或 NO 值,否则会引发异常)

public class MyEnumValidator implements ConstraintValidator<EnumChecker, MyEnum> {

  private List<MyEnum> validEnumList;

  @Override
  public void initialize(EnumChecker constraintAnnotation) {
    validEnumList = Arrays.stream(constraintAnnotation.enumClass().getEnumConstants())
        .collect(Collectors.toList());
  }
  @Override
  public boolean isValid(MyEnum value, ConstraintValidatorContext context) {
    return validEnumList.contains(value) && value.name().length() == 3;
  }
}

在此处输入图像描述

对于无效案例:

在此处输入图像描述

堆栈跟踪:

Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public java.lang.String api.sweater.controller.MainController.filter(api.sweater.request.Request): [Field error in object 'request' on field 'myenum': rejected value [NO]; codes [EnumChecker.request.myenum,EnumChecker.myenum,EnumChecker.api.sweater.request.MyEnum,EnumChecker]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [request.myenum,myenum]; arguments []; default message [myenum],class api.sweater.request.MyEnum]; default message [must be one of these values]] ]

First delete final modifier in myenum and create setter and getter for that field, because Jackson is not able to bind values from http request to your Request class for example.

public class Request {
  @EnumChecker(enumClass = MyEnum.class)
  private MyEnum myenum;
  
  public MyEnum getMyenum() {
    return myenum;
  }
  
  public void setMyenum(MyEnum myenum) {
    this.myenum = myenum;
  }
}

Then change ConstraintValidator target type to match MyEnum instead of String

public class MyEnumValidator implements ConstraintValidator<EnumChecker, MyEnum> {

  private List<MyEnum> validEnumList;

  @Override
  public void initialize(EnumChecker constraintAnnotation) {
    validEnumList = Arrays.stream(constraintAnnotation.enumClass().getEnumConstants())
        .collect(Collectors.toList());
  }
  @Override
  public boolean isValid(MyEnum value, ConstraintValidatorContext context) {
    return validEnumList.contains(value);
  }
}

Test: I did the following test

@RestController
public class MainController {

  @PostMapping("/annot")
  public String filter(@RequestBody @Valid Request req) {
    return req.getMyenum().name();
  }
}

Also I changed the implementation of MyEnumValidator to only see validation effect and prove that it takes place. (I admit that currently this validator does not make sense. Also using only @RequestBody guarantees that myenum can only Have YES or NO values otherwise throws exception)

public class MyEnumValidator implements ConstraintValidator<EnumChecker, MyEnum> {

  private List<MyEnum> validEnumList;

  @Override
  public void initialize(EnumChecker constraintAnnotation) {
    validEnumList = Arrays.stream(constraintAnnotation.enumClass().getEnumConstants())
        .collect(Collectors.toList());
  }
  @Override
  public boolean isValid(MyEnum value, ConstraintValidatorContext context) {
    return validEnumList.contains(value) && value.name().length() == 3;
  }
}

enter image description here

For a invalid case:

enter image description here

stacktrace:

Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public java.lang.String api.sweater.controller.MainController.filter(api.sweater.request.Request): [Field error in object 'request' on field 'myenum': rejected value [NO]; codes [EnumChecker.request.myenum,EnumChecker.myenum,EnumChecker.api.sweater.request.MyEnum,EnumChecker]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [request.myenum,myenum]; arguments []; default message [myenum],class api.sweater.request.MyEnum]; default message [must be one of these values]] ]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文