前言
传参时候总会遇到各式各样的传参,有些状态传参,0或1,有些不连续的数值传参像1,2, 5,有些传参须符合定义的枚举值等,本文主要重点记录自定义注解校验枚举参数
一、逻辑中枚举校验
private void checkStatus(Integer imgStatus) {
if (ObjectUtil.isEmpty(BankBannerEnums.STATUS.findByCode(imgStatus))) {
throw new CustomException(ErrorConstant.INVALID_STATUS);
}
}
public class BankBannerEnums {
public enum STATUS {
INVALID(0, "无效"),
VALID(1, "生效");
private Integer code;
private String value;
STATUS(Integer code, String value) {
this.code = code;
this.value = value;
}
public static BankBannerEnums.STATUS findByCode(Integer code) {
if (code != null) {
for (BankBannerEnums.STATUS status : BankBannerEnums.STATUS.values()) {
if (status.getCode().intValue() == code) {
return status;
}
}
}
return null;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
二、连续数字状态枚举校验
直接使用各种注解校验
@Max(value = 1)
@Min(value = 0)
private Integer status;
三、不连续数字自定义注解校验
如果状态是0,1,3 则可以用不连续数字自定义注解校验
// 元注解表示该注解可以用在的地方,此定义注解可以用在属性上
@Target(ElementType.FIELD)
// 元注解被它所注解的注解保留多久
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MyConstrictorMethod.class)
public @interface MyConstraintValidator {
int [] value();
String message() default "类型不匹配";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
@Slf4j
public class MyConstrictorMethod implements ConstraintValidator<MyConstraintValidator, Object> {
private int[] values;
@Override
public void initialize(MyConstraintValidator myConstraintValidator) {
log.info("MyConstraintValidatorMethod 初始化");
this.values = myConstraintValidator.value();
}
@Override
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
AtomicBoolean atomicValid = new AtomicBoolean(false);
if (o == null) {
//当状态为空时使用默认值
return atomicValid.get();
}
for (int value : values) {
if (value == (Integer) o) {
atomicValid.set(true);
}
}
return atomicValid.get();
}
}
@MyConstraintValidator(value = {0,1,3})
private Integer status;
注意
自测传入integer参数时候是可以传入小数的比如1.5,但是它会自动变为1传入
四、自定义注解校验枚举值
有时候传参值对应的是枚举值,所以就要求传入参数要复合枚举值数据,这种情况也有好多解决方式,上面的三种方法都可以解决,或者也可以直接使用正则注解实现
@Pattern(regexp = "1|3|01|2", message = "入参有误")
private String status;
但是在枚举有变化时,就需要更改注解内容,所以就可以定义注解直接读取枚举进行校验
自定义注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {EnumValidator.class})
public @interface EnumValid {
String message() default "请传入正确的类型";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
Class<?> target() default Class.class;
}
设置校验规则
import lombok.extern.slf4j.Slf4j;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Method;
/**
* @author guang
* @date 2023/1/8
**/
@Slf4j
public class EnumValidator implements ConstraintValidator<EnumValid, Object> {
private EnumValid annotation;
@Override
public void initialize(EnumValid constraintAnnotation) {
annotation = constraintAnnotation;
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
boolean result = false;
// 获取注解时传的target参数
Class<?> cls = annotation.target();
//String massage = annotation.massage();
// 获取这个枚举类中的枚举列表
Object[] objects = cls.getEnumConstants();
try {
// 获取枚举类中的getCode方法对象
Method method = cls.getMethod("getCode");
for (Object obj : objects) {
// obj对象反射调用getCode方法
Object code = method.invoke(obj);
// 注解的字段值与枚举实例的code进行比较,一致 则校验通过
if (value.equals(code)) {
result = true;
break;
}
}
} catch (Exception e) {
log.error("{0}不可用于@EnumValid注解,请查找原因",cls)
//massage = cls+"不可用于@EnumValid注解,请查找原因";
result = false;
}
return result;
}
}
枚举
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.stream.Stream;
/**
* @author guang
* @date 2023/1/8
**/
public enum StatusEnum {
ONE("1","one"),
TWO("2","two");
private String code;
private String desc;
StatusEnum(Integer code,String desc) {
this.code = code;
this.desc = desc;
}
@JsonValue
public Integer getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
使用
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author guang
* @date 2023/1/8
**/
@Data
@NoArgsConstructor
public class TestEntity {
private Long id;
@EnumValid(target = StatusEnum.class)
private String status;
}