说明:
参数校验是日常开发使用比较多的功能,能够比较优雅的校验参数,减少冗余的逻辑代码校验。
除了常用的@NotNull@Length@Min@Max等等这些,我们有时间需要某些参数采用我们枚举定义的值
动手:
1、引入pom依赖
<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.6</version>
</dependency>
2、自定义一个异常类ErrorResultException
**
* 统一错误结果异常
*/
public class ErrorResultException extends RuntimeException {
private int status;
private String error;
private String message;
public ErrorResultException(String message) {
this(500, message);
}
public ErrorResultException(int status, String message) {
this(status, "Internal Server Error", message);
}
public ErrorResultException(int status, String error, String message) {
super(message);
this.status = status;
this.error = error;
this.message = message;
}
public ErrorResultException(int status, String error, String message, Throwable t) {
super(message, t);
this.status = status;
this.error = error;
this.message = message;
}
public int getStatus() {
return status;
}
public String getError() {
return error;
}
@Override
public String getMessage() {
return message;
}
}
3、定义通用枚举验证工具EnumConstraintValidator
/**
* 通用枚举验证工具
*/
public class EnumConstraintValidator implements ConstraintValidator<EnumValidator, Object> {
private List<Object> values = new ArrayList<>();
@Override
public void initialize(EnumValidator annotation) {
Object[] objects = annotation.target().getEnumConstants();
Method method = ReflectUtil.getMethod(annotation.target(), annotation.method());
if (ObjectUtil.isNull(method)) {
throw new ErrorResultException(555, "Enum Error", String.format("枚举对象%s缺少名为%s的方法", annotation.target().getName(), annotation.method()));
}
try {
Object value;
for (Object obj : objects) {
value = method.invoke(obj);
values.add(value);
}
} catch (Exception e) {
throw new ErrorResultException(555, "Enum Error", "枚举验证工具初始化异常", e.getCause());
}
}
@Override
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
if (o instanceof String) {
String valueStr = (String) o;
return StrUtil.isEmpty(valueStr) || values.contains(o);
}
return ObjectUtil.isNull(o) || values.contains(o);
}
}
4、自定义一个通用枚举校验
EnumValidator
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
@Constraint(validatedBy = EnumConstraintValidator.class)
public @interface EnumValidator {
/**
* 默认错误提示
* @return
*/
String message() default "参数错误";
/**
* 指定枚举类
* @return
*/
Class<?> target();
/**
* 默认获取枚举值方法
* @return
*/
String method() default "getValue";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
实践:
1.假设枚举类:
public enum StatusEnum {
ACTIVE(1, "启用"),
FORBIDDEN(0, "禁用");
private final Integer status;
private final String title;
StatusEnum(Integer status, String title) {
this.status = status;
this.title = title;
}
public Integer getStatus() {
return status;
}
public String getTitle() {
return title;
}
}
2.VO入参字段使用校验
/**
* 任务状态
*/
@NotNull
@EnumValidator(target = TaskStatusEnum.class, method = "getCode", message = "任务状态不正确")
private Integer taskStatus;