本文涉及:无
目录
前言
背景
在上一章介绍了监听器在提取公共方法的思路,这一章配合通用业务场景进行增强。
解决方案
主要从几个方面进行修改,对于导入错误/校验不通过的记录,我们需要保存这些数据,在返回前端时进行展示提醒,方便用户感知导入结果;
RowData
public class RowData {
//行数
private Integer rowIndex;
//excel导入转换后实体类
private Object data;
public RowData(){}
public RowData(Integer rowIndex, Object data){
this.rowIndex = rowIndex;
this.data = data;
}
}
BaseDataListener
/**
* 保存错误行数及数据
*/
private final List<RowData> errorList;
/**
* 每一条数据解析时操作
*
* @param data 已经转换成实体的excel数据
* @param context EasyExcel上下文
*/
@Override
public void invoke(T data, AnalysisContext context) {
LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
//符合校验规则则添加
if (!predicate.test(data)) {
errorList.add(new RowData(
context.readRowHolder().getRowIndex()
, data));
return;
}
list.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
consumer.accept(list);
list.clear();
}
}
/**
* 获取转换异常
*
* @param exception ExcelDataConvertException
* @param context excel上下文
*/
@Override
public void onException(Exception exception, AnalysisContext context) {
// 如果是某一个单元格的转换异常 能获取到具体行号
// 如果要获取头的信息 配合doAfterAllAnalysedHeadMap使用
if (exception instanceof ExcelDataConvertException) {
ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
LOGGER.error("第{}行,第{}列解析异常", excelDataConvertException.getRowIndex() + 1,
excelDataConvertException.getColumnIndex() + 1);
errorList.add(new RowData(
context.readRowHolder().getRowIndex()
, context.readRowHolder().getCurrentRowAnalysisResult()));
}
}
/**
* 维护上传信息以供前端显示
*
* @return successRowCount:成功行数
* errorRowCount:行数
* errorRowIndex:错误行数定位
*/
public UploadMessage getUploadMessage(String errorMessage) {
return new UploadMessage(list.size(), errorList, errorMessage);
}
UploadMessage
package com.kt.common.entity.excel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* @author kwongting
* @version 1.0
* @date 2021/7/7 10:42
* @description 上传信息
*/
@Data
public class UploadMessage {
@ApiModelProperty(value = "成功行数")
private int successRowCount;
@ApiModelProperty(value = "失败行数")
private int errorRowCount;
@ApiModelProperty(value = "失败行数定位")
private List<RowData> errorRowData;
@ApiModelProperty(value = "失败错误信息")
private String errorMessage;
public UploadMessage() {
}
public UploadMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public UploadMessage(int successRowCount, List<RowData> errorRowData) {
this(successRowCount,errorRowData,null);
}
public UploadMessage(int successRowCount, List<RowData> errorRowData, String errorMessage) {
this.successRowCount = successRowCount;
this.errorRowCount = errorRowData.size();
this.errorRowData = errorRowData;
this.errorMessage = errorMessage;
}
}
EasyExcelUtil
/**
* 解析EasyExcel导入情况信息
*
* @param message BaseDataListener.getUploadMessage()
* @return 统一响应
*/
public static Response analysisUpload(UploadMessage message) {
int successRowCount = message.getSuccessRowCount();
int errorRowCount = message.getErrorRowCount();
String errorMessage = message.getErrorMessage() == null ? "请核对字段是否有误" : message.getErrorMessage();
List<RowData> rowData = message.getErrorRowData();
if (successRowCount == 0) {
return ResultUtils.error(String.format("全部导入失败,%s", errorMessage));
} else {
if (errorRowCount == 0) {
return ResultUtils.success(String.format("全部导入成功!总共%d条", successRowCount));
} else {
return ResultUtils.success(String.format("部分导入成功!成功%d条,失败%d条,%s", successRowCount, errorRowCount, errorMessage), rowData);
}
}
}
测试
@PostMapping("/upload")
public Response upload(MultipartFile file) {
return EasyExcelUtil.analysisUpload(service.upload(file));
}
public UploadMessage upload(MultipartFile file) {
BaseDataListener<TestPO> baseDataListener = new BaseDataListener<>(
po -> {
if (po的各个字段验证情况) {
return true;
}
return false;
},
mapper::insertBatchSomeColumn);
}));
try {
EasyExcel.read(file.getInputStream(), TestPO.class, baseDataListener).sheet().doRead();
} catch (IOException e) {
LOGGER.error("导入失败:[{}]", e.getMessage());
return new UploadMessage(e.getMessage());
}
return baseDataListener.getUploadMessage("请判断[字段名]是否正确");
}
至此一个简单的监听器就完毕了~下一章分享一下EasyExcel模板下载对于一些枚举字段再excel做成下拉框(数据有效性)进行更友好的输入~