使用 validation 框架生成一个校验参数是否在枚举内的校验器
说明:很多时候,前端传递的参数会是枚举,如果前后端约定好,那么传递的枚举值不会有差错,可以不需要校验。但作为后端程序员,要有安全意识,请求未必都来自前端,可能来自apifox或其他调试工具,这样传递的参数可能稀奇古怪,枚举值可能就是意料之外的,所以后端程序员还是需要校验参数值是否在枚举项内。
本文介绍如何使用 validation 框架,自定义一个校验器,校验参数值是否在枚举类之中,关于 validation 使用介绍,参考下面这篇文章:
- @Validated 使用介绍
自定义注解
创建一个注解,用于给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;@Overridepublic void initialize(InEnumeration constraintAnnotation) {this.enumClass = constraintAnnotation.enumClass();}@Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {// 没有值,不校验,默认为trueif (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 框架生成一个校验参数是否在枚举内的校验器