java学习之路学习

java 大数据量导出内部分批处理

2021-10-28  本文已影响0人  唯有努力不欺人丶

关于这个导出我翻来覆去写了不下五篇博客了,最近又遇到一个新问题:当导出的数据量过大,而且要经过复杂计算处理的话,如果一次性导出会直接oom,所以公司新做法就是内部分批写入最后统一导出。
其实原理已经说的很明了了,就是分页查询,写入sheet页,然后再查,再写。。直到结束。
不过这里因为本身分批查询需要调用dao层,而我这里又为了方便,所以采用了函数式编程。把查询本身作为参数传入。下面是完整代码:

工具类

这个接口是为了把查询作为一个函数传入。两个接收参数是分页的页码和一页条数。注意这里是用分页的形式接收,主要是为了要总条数,方便我们在导出的时候使用。第一版代码是用list接受,然后totalCount作为一个参数在导出的时候传入的。这个怎么做都可以。

@FunctionalInterface
public interface ExcelDataExt {

    Page getList(Integer page, Integer size);
}
    /**
     * 大数量分批导出
     * @param response
     * @param file
     * @param vo
     * @param ext
     */
    public void bigAlibabaExcel(HttpServletResponse response,String file, Class vo, ExcelDataExt ext) {
        logger.info(file+"导出");
        String fileName = file + System.currentTimeMillis() + ".xlsx";
        ExcelWriter excelWriter = null;
        try {
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            response.setHeader("content-Type", "application/vnd.ms-excel");
            // 这里 需要指定写用哪个class去写
            excelWriter = EasyExcel.write(response.getOutputStream(), vo).build();
            // 这里注意 如果同一个sheet只要创建一次
            WriteSheet writeSheet = EasyExcel.writerSheet(file).build();
            // 分页插入数据
            int page = 1;
            Integer totalCount = 1;
            do {
                Page pageObjVO = ext.getList(page,1000);//这个每页的条数我写死了一千,可以酌情修改
                totalCount = pageObjVO.getTotal_count();
                excelWriter.write(pageObjVO.getList(), writeSheet);
                page += 1;
            } while ((page - 1) * ExcelUtil.commonPageSize < totalCount);
        } catch (IOException e) {
            logger.error(file+"导出:" + JSON.toJSONString(e));
        } finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

实际使用

    public void exportUserList(HttpServletResponse response, UserDTO userDTO) {
        new ExcelExport().bigAlibabaExcel(response,"用户报表导出",UserVO.class, new ExcelDataExt() {
            @Override
            public Page getList(Integer page, Integer size) {
                userDTO.setPage_size(size);
                userDTO.setCurrent_page(page);
                return userMapper.getPage(userDTO);;
            }
        });
    }

这是一段伪代码,我删删减减了很多东西。但是使用起来就是这么回事,大概就是把查询条件按照查询结果写入然后导出就行了。注意我这里getPage()是自己写的查询方法,如果想用系统自带的条件构造器那么正常写就行了。
其实这个就比较灵活了,文件名传入,实现方法传入。这里有个重点是类名是什么呢?这就是导出的格式啦。

导出文件格式

简单说一下我们导出的文件肯定有表头,有顺序,甚至有时候有些字段不希望被导出来。这个时候需要用两个注解:

@ExcelProperty(value = "表头", index = 0)

这个注解是想让我们这列在excel的第index列被导出,表头是value的值

@ExcelIgnore

这个注解是指这个字段不需要被导出,忽略就可以。
我们在传入的类中每一个属性都标好注解,结果就会按照我们想要的导出啦。
本篇笔记就记到这里,如果稍微帮到你了记得点个喜欢点个关注,也祝大家工作顺顺利利!学如逆水行舟,不进则退。愿我们都能在前进的道路上一往无前!

上一篇 下一篇

猜你喜欢

热点阅读