前言
从上家公司到师大教育,一直以来,使用EasyPOI做了不少导入导出的需求,导入导出数据量从10万级到现在百万级(excel峰值103万数据量),用到了EasyPOI来完成导入,通过该篇文章我详细的整理整理EasyPOI的导入导出的基础和高级用法。
本篇文章主要涵盖一下方面内容:
- 注解说明
- 定义
EasyPoi导入实体类 - 基础的导入导出逻辑(数据校验)
- 不同类型数据的导入和导出(Map/Object)
- 基于多线程
ForkJoin实现导入优化 - 自定义导入数据处理(数据校验)
- 导入组内数据重复校验实现
- 导入组内校验实现重复行定位并输出到错误日志
常见需求场景
excel导入导出几乎在很多中后台项目都会用到,特别是一写CRM、OA、商城、企业应用等系统都十分常见,在开发的过程中我也遇到过很多excel大数据导入导出的功能,我稍微列举一些需求:
- 大数据导出数据装换以及数据加密
- excel导入数据校验,并提供错误日志下载
EasyPoi依赖
悟耕开源 EasyPoi 4.3.0版本(推荐最新)
一、注解说明
常见的5个注解类分别是:
- @Excel 作用到filed上面,是对Excel一列的一个描述
- @ExcelCollection 表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示
- @ExcelEntity 表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段
- @ExcelIgnore 和名字一样表示这个字段被忽略跳过这个导导出
- @ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理
二、定义EasyPOI实体类
三、基础的导入导出逻辑(数据校验)
easyPoi导入校验使用起来也很简单,以导入系统优化为例:
第一步,定义一个检验类SdSchoolSysUserVerify,通过实现IExcelModel、IExcelDataModel,当我们需要输出导入校验错误信息的时候,它们两个就显的很重要了,IExcelModel负责设置错误信息,IExcelDataModel负责设置行号。
第二步,定义完实体之后,那么如何实现我们的校验逻辑呢,接着自定义一个系统用户导入校验处理器SdSchoolSysUserVerifyHandler,通过实现IExcelVerifyHandler<SdSchoolSysUserVerify>,处理器里编写我们的校验逻辑:
第三步,在完成第一、二步之后,我们只需要在导入的时候通过 params.setVerifyHandler(userVerifyHandler)、params.setNeedVerfiy(true)即可以实现导入校验了。
四、不同类型数据的导入和导出(Map/Object)
在某些复杂的场景,我们导入的时候不想直接构造一个bean然后标记注解,但是中间需要处理一些字段逻辑没办法直接导入到数据库,这是用可以用map的形式导入,下面我以一个客户导入的需求演示一下如何通过map的方式导入数据:
SdCrmCustomerMapVerify
CustomerMapVerifyHandler
导入实现逻辑
核心方法:
//Map数据格式导入
ExcelImportResult<Map<String, Object>> importResult = ExcelImportUtil.importExcelMore(inputStream, Map.class, params);
// 获取导入检验通过的数据
List<Map<String, Object>> rightMapList = importResult.getList();
// 获取导入检验失败的数据
List<Map<String, Object>> failMapList = importResult.getFailList();
最后可以将校验失败的数据,通过excel错误日志输出,非常的方便。
五、基于多线程ForkJoin实现导入优化
在4.0后的版本,ExcelPoi导入支持了fork/join的线程支持,使用方法很简单 ImportParams 新加了两个参数,设置为true就可以了,多线程导入处理可以提高了导入的处理效率,比如:
params.setConcurrentTask(true); //4.1版本都支持基于fork/join的线程
六、自定义导入数据处理
这里列举说明一下EasyPoi的几个比较重要的接口和类:
- IExcelDataHandler:当存在一下比较特殊的需求场景,easyPoi基础服务无法满足客户的需求时,可以通过实现IExcelDataHandler去自定义数据处理,比如数值转换器处理。
- IExcelVerifyHandler:一般都是通过实现IExcelVerifyHandler接口实现自己的校验逻辑。
- IExcelModel:自定义实体校验类时,主要用于输出错误日志,IExcelModel负责错误信息。
- IExcelDataModel:自定义实体校验类时,主要用于输出错误日志,IExcelDataModel负责设置行号。
IExcelDataHandler
/**
* Excel 导入导出 数据处理接口
*
* @author JueYue
* 2014年6月19日 下午11:59:45
*/
public interface IExcelDataHandler<T> {
/**
* 导出处理方法
*
* @param obj 当前对象
* @param name 前字段名称
* @param value 当前值
* @return
*/
public Object exportHandler(T obj, String name, Object value);
}
七、导入组内数据重复校验实现
可以通过ThreadLocal来实现组内校验,可以定位输出每一个错误数据的具体是哪一行,方便我们做导入排错:
核心代码:
threadLocalValue.forEach(e -> {
if (e.getRegisterUserPhone().equals(customerVerify.getRegisterUserPhone())) {
int lineNumber = e.getRowNum() + 1;
joiner.add("数据与第" + lineNumber + "行重复");
}
});
//添加本行数据对象到ThreadLocal中
threadLocalValue.add(customerVerify);
threadLocal.set(threadLocalValue);