封装了easyExcel的工具类,包含字段校验功能,使用validate校验注解即可

我的未来我决定 提交于 2020-12-28 22:38:51

package com.ciics.cscloud.xinsurance.social.utils.excel;

import com.alibaba.excel.EasyExcel; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.util.StringUtils; import lombok.Data; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.util.CollectionUtils;

import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; import java.util.stream.Collectors;

/**

  • @author cxy

  • @date 2020/12/28 9:46 */ @Slf4j public class ExcelUtil {

    /**

    • 导入Excel并做数据校验
    • @param in Excel文件输入流
    • @param t 返回对象的泛型
    • @param businessValidator 业务校验的接口(自主去实现业务校验,比如:导入的用户是否已存在)
    • @param sheetNumber 第几个sheet,从0开始
    • @param headNumber 表头行号,从1开始
    • @param headMap 表头描述,map的key是第几列(从0开始),value是表头第几列对应的内容,用来校验Excel格式,如果不传,则取返回实体@ExcelProperty的value属性做校验
    • @param <T>
    • @return */ public static <T extends BaseExcelDto> ImportResult importExcelAndValidate(InputStream in, T t, BusinessValidator businessValidator, int sheetNumber, int headNumber, Map<Integer, String> headMap) { ExcelModelListener<T> modelListener = new ExcelModelListener<>(headMap, t.getClass()); EasyExcel.read(in, t.getClass(), modelListener).sheet(sheetNumber).headRowNumber(headNumber).doRead(); ArrayList<T> successList = modelListener.successList; ImportResult result = businessValidator.validate(successList); if (result == null) { result = new ImportResult<>(); result.setFailedData(modelListener.failedList); result.setFailedMsg(modelListener.failedMsg); result.setSuccessData(successList); } else { if (!CollectionUtils.isEmpty(result.getFailedData())) { result.getFailedData().addAll(modelListener.failedList); result.getFailedMsg().addAll(modelListener.failedMsg); } else { result.setFailedMsg(modelListener.failedMsg); result.setFailedData(modelListener.failedList); } } return result; }

    /**

    • Excel导入返回实体

    • @param <T> / @Data public static class ImportResult<T extends BaseExcelDto> { /*

      • 导入状态,全部成功true,有失败几率false / private Boolean importStatus; /*
      • 成功记录(校验合法的数据) / private List<T> successData; /*
      • 校验不合法的数据 / private List<T> failedData; /*
      • 错误信息 */ private List<String> failedMsg;

      public Boolean getImportStatus() { return CollectionUtils.isEmpty(failedData); } }

    /**

    • excel基类,统一存储行号字段
    • @param <T> */ @Data public static class BaseExcelDto<T> { private Integer rowNumber; }

    /**

    • 业务校验的接口

    • @param <T> */ public interface BusinessValidator<T extends BaseExcelDto> {

      /**

      • 业务校验(校验数据是否符合业务要求,比如;用户不能重复)
      • @param excelData
      • @return */ ImportResult<T> validate(List<T> excelData);

    }

    static class ExcelModelListener<T> extends AnalysisEventListener<T> { private Class classz; private final ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); private final Validator beanValidator = factory.getValidator(); private List<String> failedMsg; private Map<Integer, String> head; private static final String ERR_MSG = "第--%d--行"; private ArrayList<T> failedList = new ArrayList<>(); private ArrayList<T> successList = new ArrayList<>();

     public ExcelModelListener(Map<Integer, String> headMap, Class c) {
         failedMsg = new ArrayList<>();
         head = headMap;
         classz = c;
     }
    
     /**
      * 解析行数据时做必填校验
      *
      * @param data
      * @param context
      */
     @Override
     public void invoke(T data, AnalysisContext context) {
         int rouNumber = context.readRowHolder().getRowIndex() + 1;
         Method method = BeanUtils.findMethod(data.getClass(), "setRowNumber", Integer.class);
         if (null != method) {
             try {
                 method.invoke(data, rouNumber);
             } catch (IllegalAccessException e) {
                 e.printStackTrace();
             } catch (InvocationTargetException e) {
                 e.printStackTrace();
             }
         }
         Set<ConstraintViolation<T>> violationSet = beanValidator.validate(data);
         if (!CollectionUtils.isEmpty(violationSet)) {
             List<String> messages = violationSet.stream().map(ConstraintViolation::getMessage).collect(Collectors.toList());
             String join = org.apache.commons.lang3.StringUtils.join(messages, ",");
             failedMsg.add(String.format(ERR_MSG, rouNumber) + ":" + join);
             failedList.add(data);
         } else {
             successList.add(data);
         }
     }
    
     /**
      * 校验表头
      *
      * @param headMap
      * @param context
      */
     @SneakyThrows
     @Override
     public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
         if (null == head) {
             head = getIndexNameMap(classz);
         }
         if (CollectionUtils.isEmpty(head)) {
             return;
         }
         Set<Integer> keySet = head.keySet();
         for (Integer key : keySet) {
             if (StringUtils.isEmpty(headMap.get(key))) {
                 throw new ExcelAnalysisException("解析excel出错,请传入正确格式的excel");
             }
             if (!headMap.get(key).equals(head.get(key))) {
                 log.info(headMap.get(key));
                 log.info(head.get(key));
                 throw new ExcelAnalysisException("解析excel出错,请传入正确格式的excel");
             }
         }
     }
    
     @Override
     public void doAfterAllAnalysed(AnalysisContext context) {
         log.info("导入完成!");
    
     }
    
     public Map<Integer, String> getIndexNameMap(Class clazz) throws NoSuchFieldException {
         Map<Integer, String> result = new HashMap<>();
         Field field;
         Field[] fields = clazz.getDeclaredFields();
         for (int i = 0; i < fields.length; i++) {
             field = clazz.getDeclaredField(fields[i].getName());
             field.setAccessible(true);
             ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
             if (excelProperty != null) {
                 int index = excelProperty.index();
                 String[] values = excelProperty.value();
                 StringBuilder value = new StringBuilder();
                 for (String v : values) {
                     value.append(v);
                 }
                 result.put(index, value.toString());
             }
         }
         return result;
     }
    

    }

}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!