使用 validation 框架生成一个校验参数是否在枚举内的校验器

发布于:2025-07-21 ⋅ 阅读:(19) ⋅ 点赞:(0)

说明:很多时候,前端传递的参数会是枚举,如果前后端约定好,那么传递的枚举值不会有差错,可以不需要校验。但作为后端程序员,要有安全意识,请求未必都来自前端,可能来自apifox或其他调试工具,这样传递的参数可能稀奇古怪,枚举值可能就是意料之外的,所以后端程序员还是需要校验参数值是否在枚举项内。

本文介绍如何使用 validation 框架,自定义一个校验器,校验参数值是否在枚举类之中,关于 validation 使用介绍,参考下面这篇文章:

自定义注解

创建一个注解,用于给DTO属性打上标记

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

/**
 * 校验参数是否在枚举中
 */
@Documented
@Constraint(validatedBy = InEnumerationValidator.class)
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface InEnumeration {

    String message() default "参数值不在枚举中";

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

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

    Class<? extends Enum<?>> enumClass();
}

校验器

校验实现,获取DTO字段值与指定枚举类查询、比较,返回校验结果。

注意这里获取枚举项编码的方法是 getCode,如果后面创建的枚举类,获取编码的方法不叫这个,会报错的。

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 参数是否在枚举内校验器
 */
public class InEnumerationValidator implements ConstraintValidator<InEnumeration, String> {

    private Class<? extends Enum<?>> enumClass;

    @Override
    public void initialize(InEnumeration constraintAnnotation) {
        this.enumClass = constraintAnnotation.enumClass();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        // 没有值,不校验,默认为true
        if (value == null) {
            return true;
        }

        try {
            // 假设枚举有一个 getCode() 方法返回你想要校验的值
            Method getCodeMethod = enumClass.getMethod("getCode");
            Object[] enumConstants = enumClass.getEnumConstants();

            return Arrays.stream(enumConstants)
                    .map(e -> {
                        try {
                            return getCodeMethod.invoke(e);
                        } catch (Exception ex) {
                            return null;
                        }
                    })
                    .anyMatch(code -> code != null && code.toString().equals(value));
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
}

使用

定义一个枚举类,如下,注意要生成 getCode() 方法,不然校验器里拿不到,校验那会报错,我这用 @Getter 注解生成了。

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 季节枚举
 */
@AllArgsConstructor
@Getter
public enum SeasonEnum {

    SPRING("spring", "春天"),

    SUMMER("summer", "夏天"),

    AUTUMN("autumn", "秋天"),

    WINTER("winter", "冬天");

    public final String code;

    private final String desc;
}

在参数对象的属性上,指定枚举类和校验不通过时的返回信息

import com.hezy.annotation.InEnumeration;
import com.hezy.enums.SeasonEnum;
import lombok.Data;

/**
 * 参数
 */
@Data
public class Param {

    @InEnumeration(enumClass = SeasonEnum.class, message = "季节不正确,不在枚举内")
    private String season;
}

创建一个接口,如下:

    @PostMapping("/enum")
    public String demo4(@RequestBody @Validated Param param) {
        return "success";
    }

启动项目,测试,“大夏天”不在枚举项内,返回错误

在这里插入图片描述

“summer”在枚举内,返回成功

在这里插入图片描述

总结

本文介绍如何使用 validation 框架生成一个校验参数是否在枚举内的校验器


网站公告

今日签到

点亮在社区的每一天
去签到