API请求参数中的枚举值校验问题,具有普遍性。
开门见山,用真实代码来进行演示!
接口请求参数
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StationStatusRequest {
@JsonProperty("OperatorId")
@NotEmpty(message = "运营商编码不可为空")
@ApiModelProperty(value = "运营商ID")
private String operatorId;
@JsonProperty("ConnectorId")
@NotEmpty(message = "充电接口编码不可为空")
@ApiModelProperty(value = "充电接口编码")
private String connectorId;
@JsonProperty("Status")
@EnumConstraint(value = StationStatusEnum.class, message = "充电设备接口状态非法,不在枚举范围内")
@ApiModelProperty(value = "充电设备接口状态")
private Integer status;
}
StationStatusEnum枚举类
接口请求参数status的值,对应于StationStatusEnum枚举类的code!
/**
* 充电设备接口状态 0:离网,1:空闲,2:占用
*
* @author xuej
*
*/
@Getter
@AllArgsConstructor
public enum StationStatusEnum {
OFF_LINE(0, "离网"),
IDLE(1, "空闲"),
OCCUPIED(2, "占用"),
;
/**
* 异常码
*/
private final Integer code;
/**
* 异常信息
*/
private final String message;
/**
* 解析异常码
*
* @param code
* @return
*/
public static StationStatusEnum parse(Integer code) {
StationStatusEnum e = resolve(code);
if (e == null) {
throw new IllegalArgumentException("当前异常码不存在 [" + code + "]");
}
return e;
}
/**
* 转化异常码
*
* @param code
* @return
*/
private static StationStatusEnum resolve(Integer code) {
for (StationStatusEnum e : values()) {
if (Objects.equals(e.code, code)) {
return e;
}
}
return null;
}
}
自定义注解@EnumConstraint
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD })
@Constraint(validatedBy = EnumConstraintValidator.class)
public @interface EnumConstraint {
Class<?> value();
String message() default "参数不在枚举范围内";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
自定义注解@EnumConstraintValidator
@Slf4j
public class EnumConstraintValidator implements ConstraintValidator<EnumConstraint, Object>, Annotation {
private List<Object> values = new ArrayList<>();
@Override
public void initialize(EnumConstraint enumValidator) {
Class<?> clz = enumValidator.value();
Object[] ojects = clz.getEnumConstants();
try {
Method method = clz.getMethod("getCode");
if (Objects.isNull(method)) {
throw new Exception(String.format("枚举对象%s缺少字段code", clz.getName()));
}
Object value = null;
for (Object obj : ojects) {
value = method.invoke(obj);
values.add(value);
}
} catch (Exception e) {
log.error("枚举校验初始化处理失败,原因 = {},", Throwables.getStackTraceAsString(e));
}
}
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
return Objects.isNull(value) || values.contains(value);
}
}