java在使用easyexcel官方文档时导入文件时如何校验多行表头,且数据不固定?

/**
* 处理每行数据
*/
@Override
public void invoke(Model model, AnalysisContext analysisContext) {
if (model.getName.length()>20) {
throw new ExcelAnalysisException("姓名过长");
}
}
/**
* 接收invoke中的异常,将异常处理抛出到service
*
* @author jamin
* @date 2020/7/30 10:28
*/
@Override
public void onException(Exception exception, AnalysisContext context) throws Exception {
//获取行号
Integer index = context.readRowHolder().getRowIndex() + 1;
//invoke中的异常
if (exception instanceof ExcelAnalysisException) {
ExcelAnalysisException excelAnalysisException = (ExcelAnalysisException) exception;
String message = excelAnalysisException.getMessage();
throw new ExcelAnalysisStopException("[数据处理异常--第" + index + "行]----" + message);
}
throw new ExcelAnalysisStopException("[数据解析异常] 请检查文件");
}
/**
* 导入数据
*
* @author jamin
* @date 2020/7/30 10:37
*/
public MessageVo importData(MultipartFile file) {
Map<String, String> map = new HashMap<>();
map.put("code","0");
try {
EasyExcel.read(file.getInputStream()).autoCloseStream(true).autoTrim(true).headRowNumber(2).head(Model.class).registerReadListener(new ExcelListener()).sheet(0).doRead();
} catch (Exception ex) {
map.put("code","1");
map.put("msg",ex.getCause().getMessage());
}
}
前言JAVA解析Excel工具EasyExcel的初次使用easyExcel git地址:https://github.com/alibaba/easyexcel一、EasyExcelJava解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便二、背景及解决本公司一个相对时间较长的一个SpringBoot项目,系统原有导入Excel偶尔会发生OOM,原有导入功能对导入excel大小限制进行规避。业务新需求中,涉及到了excel的导入,趁此机会使用easyExcel,为调整原有导入发生OOM做好准备。由于原项目中使用的POI版本未3.16,此次升级POI 3.17(不升级easyExcel异常)升级方法调整借鉴:https://www.csdn.net/tags/OtDacg4sNzM2NTUtYmxvZwO0O0OO0O0O.html主要问题系统使用人员将excel导入后,需要立即知道结果;若数据落库过程中出现了异常,使用人员需要通过系统反馈进行excel内容调整后再次操作。但是重写easyExcel是未对异常进行处理的, 同时本次导入Excel及其简单且每次导入数据量有限,所以将excel中所有的数据取出后,统一验证,若有问题再进行抛出。导入excel校验返回代码如下:
public Map importData(@RequestParam(value = "filename") MultipartFile file) {
ExcelReader excelReader = null;
List<InteractiveUploadDto> deleteList = new ArrayList<>();
List<InteractiveUploadDto> addList = new ArrayList<>();
// 数据读取异常统一抛出
try {
excelReader = EasyExcelFactory.read(file.getInputStream(), InteractiveUploadDto.class,
new InteractiveUploadListener( deleteList,addList)).build();
ReadSheet readSheet = EasyExcelFactory.readSheet(0).build();
excelReader.read(readSheet);
} catch (MyException e) {
throw new MyException("导入Excel识别异常"+e.getMessage());
}finally {
if (excelReader != null){
excelReader.finish();
}
}
// 异常放在了interactiveRemindInfoService捕捉处理
// 将excel中所有的数据读取到了list内, 然后在service层处理时,如果有异常会throw到页面
int save = interactiveRemindInfoService.excelDataSave(addList);
int delete = interactiveRemindInfoService.excelDataDelete(deleteList);
return getSuccessMap("数据处理成功,保存成功记录数:"+save+" 条后删除成功记录数:"+delete+" 条,请仔细核对!");
}
public class InteractiveUploadListener extends AnalysisEventListener<InteractiveUploadDto> {
private static final Logger LOGGER = LoggerFactory.getLogger(InteractiveUploadListener.class);
private List<InteractiveUploadDto> deleteList ;
private List<InteractiveUploadDto> addList ;
// 通过构造参数,将excel中的数据通过业务区分,并返回到相应的service。
//业务也可以在此类中进行处理。异常沟通构造参数传回service层,然后再抛出
public InteractiveUploadListener(List<InteractiveUploadDto> deleteList, List<InteractiveUploadDto> addList){
this.deleteList = deleteList;
this.addList = addList;
}
@Override
public void invoke(InteractiveUploadDto vo, AnalysisContext analysisContext) {
LOGGER.info("收数据导入,解析第{}行数据:{}" , analysisContext.readRowHolder().getRowIndex() , vo);
// 由于本功能导入数据量肯定不大,所以这里就不在进行分批处理了。 (不建议如此处理 OOM)
this.buildEntity(vo);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
LOGGER.info("数据处理完成");
}
/**
* @desc
将每行数据,通过业务类型进行区分放入不同的集合中
* @param dto : excel内的每行数据信息
*/
private void buildEntity(InteractiveUploadDto dto) {
// 将每行数据进行区分, 删除操作放入deleteList集合内, 新增放入addList集合内
if (dto.getDeleteOrNot().equals("Y")){
deleteList.add(dto);
}else {
addList.add(dto);
}
}
}
/**
* @desc
* ExcelProperty与导入的Excel一一对应
*/
public class InteractiveUploadDto {
@ExcelProperty(value = "合同号")
@NotBlank(message = "不能为空")
private String applicationNumber;
@ExcelProperty(value = "待分配用户")
private String username;
@ExcelProperty(value = "是否删除")
@NotBlank(message = "是否删除列不能为空")
private String deleteOrNot;
private Long userId;
}
由于本次功能较为简单,数据未进行批次处理,同时我是将业务处理在excel数据解析后,返回了service处理, 在数据处理过程中或校验时,有异常会直接抛到前端。文件导出待补充总结

我要回帖

更多关于 easyexcel官方文档 的文章

 

随机推荐