使用validator实现枚举类型校验

使用validator实现枚举类型校验

前言: 在前端调用后端接口传递参数的过程中,我们往往需要对前端传递过来的参数进行校验,比如说我们此时需要对用户的状态进行更新,而用户的状态只有正常和已删除,并且是在代码中通过枚举已经定义好的了。此时我们在校验前端传递过来的状态字段的时候,就可以使用validator对状态字段进行校验

1. 解决思路

我们有两种方式可以实现:

  1. 使用validator的@Pattern 注解,此时我们需要将userStatus的类型改为String类型
    @Pattern(regexp = “^[1-2]$”, message = “Status must be 1 or 2”)
  2. 使用自定义枚举校验器

下面我们来重点讲解一下如何基于自定义枚举校验器来实现对枚举类型字段的校验

2. 实现方式

2.1 创建自定义枚举

@Documented
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
@Repeatable(EnumValidation.List.class) // 允许在同一元素上多次使用该注解
@Constraint(validatedBy = {EnumValidator.class})
public @interface EnumValidation {
    String message() default "{*.validation.constraint.Enum.message}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    Class<?> clazz();

    String method() default "ordinal";

    @Documented
    @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
    @Retention(RUNTIME)
    @interface List {
        EnumValidation[] value();
    }
}

2.2 创建自定义枚举校验器

/**
 * @desc: 枚举验证器
 * @author: shy
 * @date: 2023/11/13 16:43
 */
public class EnumValidator implements ConstraintValidator<EnumValidation, Object> {

    private EnumValidation annotation;

    @Override
    public void initialize(EnumValidation constraintAnnotation) {
        this.annotation = constraintAnnotation;
    }
    
    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        if (value == null) {
            return false;
        }
        Object[] objects = annotation.clazz().getEnumConstants();
        try {
            Method method = annotation.clazz().getMethod(annotation.method());
            for (Object o : objects) {
                if (value.equals(method.invoke(o))) {
                    return true;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return false;
    }
}

2.3 用户状态枚举

属性的get方法必须要实现,此处直接使用Lombok

/**
 * @desc: 用户状态枚举
 * @author: shy
 * @date: 2022/2/4 0:36
 */
@Getter
public enum UserStatusEnum {
    正常(1),
    已删除(2);

    final int value;

    UserStatusEnum(int value) {
        this.value = value;
    }
}

2.4 枚举添加

此时我们就可以直接在相应的字段上加上自定义好的注解

@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@ApiModel(description = "用户更新参数")
public class UserUpdateParam implements Serializable {

    private static final long serialVersionUID = -484458568568755349L;

    @ApiModelProperty(value = "用户id", name = "userId", required = true)
    @NotNull(message = "用户id不能为空")
    Integer userId;

    @ApiModelProperty(value = "用户状态", name = "userStatus", required = true)
    @EnumValidation(clazz = UserStatusEnum.class, method = "getValue", message = "用户状态不合法")
    Integer userStatus;
}

3. 测试

此时我们调用更新接口进行,就可以看到如下结果:
使用validator实现枚举类型校验_第1张图片
至此,大功告成!

4. 总结

一开始的时候是想通过@Max和@Min的方式去实现,但是觉着那样的方式不够优雅,而且用户如果新增了别的状态,涉及到状态校验的地方都需要改动,涉及范围比较广,所以想到了这样的方式。

欢迎大家借鉴参考~

你可能感兴趣的:(Java,java,spring,boot,hibernate)