使用自定義注解實現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
方法進行校驗。
@Overridepublic 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數據導入時的枚舉值校驗。這樣不僅提高了代碼的可維護性,還使得代碼更加簡潔和易讀。