1.excel基类,统一存储行号字段
import lombok.Data;
/**
* excel基类,统一存储行号字段
*/
@Data
public class BaseExcelDto {
private Integer rowNumber;
}
2.业务校验的接口
import java.util.*;
/**
* 业务校验的接口
*/
public interface BusinessValidator {
/**
业务校验(校验数据是否符合业务要求,比如;用户不能重复)
@param excelData
@return
*/
ImportResult validate(List excelData);
}
3.导入结果类
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import lombok.Data;
import java.util.List;
@Data
public class ImportResult {
// 导入状态,全部成功true,有失败几率false
private Boolean importStatus;
// 成功记录(校验合法的数据)
private List successData;
// 检验不合法的数据
private List failedData;
// 错误信息
private List failedMsg;
//
public Boolean getImportStatus() {
return CollectionUtils.isEmpty(failedData);
}
}
4.ExcelModelListener(excel监听)
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.nacos.client.naming.utils.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author 三十七度
*/
public class ExcelModelListener extends AnalysisEventListener{
private Class classz;
private final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
private final Validator beanValidator = factory.getValidator();
private List failedMsg;
private Map head;
private static final String ERR_MSG = "第--%d--行";
private ArrayList failedList = new ArrayList<>();
private ArrayList successList = new ArrayList<>();
public ExcelModelListener(Map headMap, Class c) {
failedMsg = new ArrayList<>();
head = headMap;
classz = c;
}
/**
* 解析行数据时做必填校验
*
* @param
* @param
*/
@Override
public void invoke(Object 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();
}
}
// TODO
Set<ConstraintViolation<Object>> violationSet = beanValidator.validate(data);
if (!CollectionUtils.isEmpty(violationSet)) {
List 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 context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
if (null == head) {
try {
head = getIndexNameMap(classz);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
if (CollectionUtils.isEmpty((Collection) head)) {
return;
}
Set keySet = head.keySet();
for (Object key : keySet) {
if (StringUtils.isEmpty((CharSequence) head.get(key))) {
throw new ExcelAnalysisException("解析excel出错,请传入正确格式的excel");
}
if (!head.get(key).equals(head.get(key))) {
// log.info(head.get(key));
System.out.println(head.get(key));
throw new ExcelAnalysisException("解析excel出错,请传入正确格式的excel");
}
}
}
public static Map getIndexNameMap(Class clazz) throws NoSuchFieldException {
Map 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;
}
}
5.excelUtils(工具)
import com.alibaba.excel.EasyExcel;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Map;
@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
* @return
*/
public static ImportResult importExcelAndValidate(InputStream in, T t, BusinessValidator businessValidator, int sheetNumber, int headNumber, Map headMap) {
ExcelModelListener modelListener = new ExcelModelListener(headMap, t.getClass());
EasyExcel.read(in, t.getClass(), modelListener).sheet(sheetNumber).headRowNumber(headNumber).doRead();
ArrayList 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;
}
}
全部已整理好,希望能够帮助需要的人,创作不易(转载请表明出处),有问题请评论区留言。
👍如果对你有帮助,给博主一个免费的点赞以示鼓励
欢迎各位🔎点赞👍评论收藏⭐️