使用阿里的EasyExcel导入数据

工作遇到一种情况,在导入excel的时候数量过多,导致占用内存太大最终OOM.为了避免这样的情况再次出现,更换easyPoi为EasyExcel,它是一行一行读,非常节省内存且快速.
首先依赖

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel-core</artifactId>
            <version>3.2.1</version>
        </dependency>

然后java对象,注意该java对象的顺序要跟excel的列顺序完全一一对应,不需要@Excel注解,该注解是之前easyPoi的遗留,我删除了一些无用字段,反正不重要

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ClientImportDTO {
    @Excel(name = "客户姓名")
    private String name;
    @Excel(name = "手机号")
    private String phone;
    @Excel(name = "获客渠道")
    private String source;
    @Excel(name = "微信号")
    private String wechat;
    @Excel(name = "客户星级")
    private String level;
    @Excel(name = "意向金额")
    private String wantAmount;
    @Excel(name = "贷款目的")
    private String purpose;
    @Excel(name = "性别")
    private String gender;
}

然后是重点,EasyExcel采用Listener来对excel进行操作

@Slf4j
public class ClientImportDTOListener implements ReadListener<ClientImportDTO> {
//这是队列长度,达到这个数量的时候就结束一波,这里数量过大依然会占用内存,正常50,100就可以
    private static final int BATCH_COUNT = 50;
    private List<ClientImportDTO> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    @Getter
    private List<ClientImportDTO> allDataList = new ArrayList<>();

//这里是一条一条解析数据,然后加到上面的list中
    @Override
    public void invoke(ClientImportDTO data, AnalysisContext context) {
        //log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        if (cachedDataList.size() >= BATCH_COUNT) {
            allDataList.addAll(cachedDataList);
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }
//这里是解析完成之后执行的内容,比如存库就可以直接在这里存,但是因为我要做其他操作所以是做了一个getAllList的操作,全部拿到了再去做其他事情
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        allDataList.addAll(cachedDataList);
        log.info("所有数据解析完成,收集到 {} 条数据", allDataList.size());
    }

}

重点基本都在代码注释中.然后是最后的controller方法

    @ApiOperation("个人线索excel导入")
    @PostMapping("/importClue")
    public R importClue(MultipartFile file) throws Exception {
        long start = System.currentTimeMillis();
        // 使用 EasyExcel 读取数据
        ClientImportDTOListener listener = new ClientImportDTOListener();
        EasyExcel.read(file.getInputStream(), ClientImportDTO.class, listener).sheet().doRead();
        // 获取所有数据
        List<ClientImportDTO> userList = listener.getAllDataList();
        long end = System.currentTimeMillis();
        log.info("当前导入的个人线索列表数量为{}, 耗时{}毫秒", userList.size(), end - start);
        // 调用 importBatch2 方法处理业务逻辑
        return clueService.importBatch2(userList);
    }

完事.实测非常优秀,3000条数据仅需100多毫秒

你可能感兴趣的:(java)