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