用自定义注解实现Excel数据导入中的枚举值校验
使用自定义注解实现Excel数据导入中的枚举值校验
在实际开发中,我们经常需要从Excel文件中导入数据,并且这些数据需要符合一定的规则,比如某些字段的值必须是预定义的枚举值。本文将介绍如何使用自定义注解来实现这一功能,以提高代码的可维护性和可读性。
1. 定义自定义注解
首先,我们需要定义一个自定义注解FieldEnum
,用于标记需要进行枚举值校验的字段。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 字段枚举信息配置
*
* @author liusy
* @since 2022/05/30 15:57 星期一
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.FIELD, ElementType.PARAMETER})
public @interface FieldEnum {
/**
* 枚举类型,从数据库枚举表中校验
*/
String type() default "";
/**
* 是否是组合枚举,多个用,分割
*/
boolean isEnumGroup() default false;
/**
* 设置本地枚举列表,默认为空,如果设置将从本地枚举列表中获取进行对比
*
* @return 本地枚举列表
*/
String[] localEnumList() default {};
}
2. 实现校验逻辑
接下来,我们需要实现一个工具类ValidateUtil
,用于校验带有FieldEnum
注解的字段。
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.inspur.planning.flow.annotation.FieldEnum;
import com.inspur.planning.flow.exception.CustomException;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import java.lang.reflect.Field;
import java.util.*;
/**
* @author liusy
* @since 2023/03/16 14:40 星期四
*/
public class ValidateUtil {
public static <T> void validateEnum(T bean) {
List<String> errorMsgList = new ArrayList<>();
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Object val = getFieldValue(field, bean);
if (ObjectUtil.isEmpty(val)) {
continue;
}
FieldEnum fieldEnum = field.getAnnotation(FieldEnum.class);
if (fieldEnum != null) {
validateFieldEnum(fieldEnum, val, errorMsgList);
}
}
if (!errorMsgList.isEmpty()) {
throw new CustomException(String.join(";", errorMsgList));
}
}
private static Object getFieldValue(Field field, Object bean) {
try {
return field.get(bean);
} catch (IllegalAccessException e) {
throw new RuntimeException("反射获取字段值失败", e);
}
}
private static void validateFieldEnum(FieldEnum fieldEnum, Object val, List<String> errorMsgList) {
String name = val.toString();
// 本地枚举校验
if (fieldEnum.localEnumList().length > 0) {
if (!Arrays.asList(fieldEnum.localEnumList()).contains(name)) {
errorMsgList.add(name + "不是枚举值,请按照枚举填写");
}
}
if(StrUtil.isNotEmpty(fieldEnum.type())){
// 数据库查询校验
if (fieldEnum.isEnumGroup()) {
String[] split = name.split(",");
for (String item : split) {
if (!checkIsEnum(fieldEnum.type(), item)) {
errorMsgList.add(item + "不是枚举值,请按照枚举填写");
}
}
} else {
if (!checkIsEnum(fieldEnum.type(), name)) {
errorMsgList.add(name + "不是枚举值,请按照枚举填写");
}
}
}
}
private static boolean checkIsEnum(String type, String name) {
JdbcTemplate jdbcTemplate = SpringUtil.getBean(JdbcTemplate.class);
String sql = "select count(1) from PL_ENUMERATION where TYPE = ? and NAME = ? and STATEFLAG = 0";
return jdbcTemplate.queryForObject(sql, Integer.class, type, name) > 0;
}
}
3. 在数据模型中使用注解
在需要进行枚举值校验的字段上添加FieldEnum
注解。
@Data
public class ImporTaskDTO {
/**
* 任务状态
*/
@NotEmpty(message = "任务状态不能为空")
@FieldEnum(localEnumList = {"施工中,未提交完工", "提交送审", "已提交完工未送审"})
@ExcelProperty("任务状态【必填】")
private String taskStatus;
/**
* 是否有问题
*/
@FieldEnum(localEnumList = {"是", "否"})
@NotEmpty(message = "是否有问题不能为空")
@ExcelProperty("是否有问题【必填】")
private String existsProblem;
/**
* 问题重要程度
*/
@FieldEnum(type = "PROBLEM_LEVEL", isEnumGroup = false)
private String problemLevel;
/**
* 检查方式
*/
@NotEmpty(message = "检查方式不能为空")
@ExcelProperty("检查方式【必填】")
private String checkType;
}
4. 在业务逻辑中调用校验方法
在导入Excel数据的方法中调用ValidateUtil.validateEnum
方法进行校验。
@Override
public List<QualityManageOrder> analysisExcel(MultipartFile file) {
List<ImportTaskDTO> dataList = new ArrayList<>();
try {
EasyExcel.read(file.getInputStream(), ImportQualityManageTaskDTO.class, new PageReadListener<ImportTaskDTO>(readList -> {
dataList.addAll(readList);
})).sheet().doRead();
} catch (IOException e) {
throw new CustomException("读取文件失败");
}
// 校验数据,并且填充基本任务数据
ValidateUtil.validateEnum(dataList);
// 其他业务逻辑...
return orderList;
}
通过以上步骤,我们就可以使用自定义注解实现Excel数据导入时的枚举值校验。这样不仅提高了代码的可维护性,还使得代码更加简洁和易读。