4
触发Bug的代码
//初始化监听器
CustomListener workOrderListener = new CustomListener(workOrderService, fileVersionNo, now);
//解析第一个sheet数据
try {
EasyExcel.read(file.getInputStream(), workOrderListener).sheet(0).doReadSync();
} catch (Exception e) {
return BaseResponse.error("期别计划sheet" + e.getMessage());
}
//解析第二个sheet数据
try {
EasyExcel.read(file.getInputStream(), workOrderListener).sheet(1).doReadSync();
} catch (Exception e) {
return BaseResponse.error("日别计划sheet" + e.getMessage());
}
public class CustomListener extends AnalysisEventListener<Map<Integer, String>> {
private final static Logger logger = LoggerFactory.getLogger(CustomListener.class);
/**
* 实际使用中可以3000条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 1000;
@Resource
private final CustomExcelService customExcelService;
@Resource
private String fileVersionNo;
@Resource
private Date now;
/**
* 用list集合保存解析到的结果
*/
List<Map<Integer, Map<Integer, String>>> list = new ArrayList<>();
/**
* 重构,把传来的值赋给对应的属性
*
* @param customExcelService 自定义excel接口类
*/
public CustomListener(CustomExcelService customExcelService, String fileVersionNo, Date now) {
this.customExcelService = customExcelService;
this.fileVersionNo = fileVersionNo;
this.now = now;
list = new ArrayList<>();
}
/**
* 重写invokeHeadMap方法,获去表头,如果有需要获取第一行表头就重写这个方法,不需要则不需要重写
*
* @param headMap Excel每行解析的数据为Map<Integer, String>类型,Integer是Excel的列索引,String为Excel的单元格值
* @param context context能获取一些东西,比如context.readRowHolder().getRowIndex()为Excel的行索引,表头的行索引为0,0之后的都解析成数据
*/
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
logger.info("解析到一条头数据:{}, currentRowHolder: {}", headMap.toString(), context.readRowHolder().getRowIndex());
Map<Integer, Map<Integer, String>> map = new HashMap<>();
map.put(context.readRowHolder().getRowIndex(), headMap);
list.add(map);
}
/**
* 重写invoke方法获得除Excel第一行表头之后的数据,
* 如果Excel第二行也是表头,那么也会解析到这里,如果不需要就通过判断context.readRowHolder().getRowIndex()跳过
*
* @param data 除了第一行表头外,数据都会解析到这个方法
* @param context 和上面解释一样
*/
@SneakyThrows
@Override
public void invoke(Map<Integer, String> data, AnalysisContext context) {
logger.info("解析到一条数据:{}, currentRowIndex: {}----", data.toString(), context.readRowHolder().getRowIndex());
Map<Integer, Map<Integer, String>> map = new HashMap<>();
map.put(context.readRowHolder().getRowIndex(), data);
list.add(map);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
logger.info("保存数据开始---!");
saveData();
logger.info("保存数据结束---!");
// 存储完成清理 list
list.clear();
logger.info("存储完成清理,list成功");
}
}
/**
* 解析到最后会进入这个方法,需要重写这个doAfterAllAnalysed方法,然后里面调用自己定义好保存方法
*
* @param context 解析上下文
*/
@SneakyThrows
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
logger.info("所有数据解析完成!");
list.clear();
logger.info("list数据清除成功");
}
/**
* 加上存储数据库
*/
private void saveData() throws Exception {
logger.info("{}条数据,开始存储数据库!", list.size());
customExcelService.saveForExcel(list, fileVersionNo, now);
list.clear();
}
提示的异常或者没有达到的效果