之前也做过关于Excel的导出案例,此次也是在其基础上进行改造升级:
但是之前的导出存在这么几个问题:
-
如果是数据量很大容易导致页面卡死(我曾导出30w条数据,直接导致OOM) -
用户体验很糟糕,数据量一多就会等很久,而且用户没办法做别的事情。 -
每次点击导出都需要走一遍完整的导出过程(这个其实还好) -
没办法对每次导出的数据进一个规整
今天使用异步导出来解决上述问题。
一、UML图
1-1、导出图
1-2、下载图
从上面的图中可以看出,整个下载是异步的,用户不需要在页面等待,每次导出我们都生成一个记录和一个文件,用户可以多次下载。
二、功能实现
2-1、记录实体
/**
* Excel列表数据
*
* @author 小道仙97
* @date 2021/8/8
*/
public class ExcelList {
/**
* id
*/
private String id;
/**
* 文件名
*/
private String name;
/**
* 下载行数
*/
private Integer rows;
/**
* 下载耗时
*/
private Long takeUpTime;
/**
* 下载地址
*/
private String downloadUrl;
}
2-2、Controller
import javax.servlet.http.HttpServletResponse;
import java.util.*;
/**
* Excel导出
*
* @author 小道仙97
* @date 2021-08-08
*/
@RestController
public class ExportExcelController {
@Autowired
private ExportExcel exportExcel;
// 模仿下载列表
public static List<ExcelList> list = new ArrayList<>(10);
/**
* Excel 导出
* @throws Exception
*/
@GetMapping("/excel/export")
public void export() {
Long startTime = System.currentTimeMillis();
String name = "Excel异步导出测试" + UUID.randomUUID().toString() + ".xlsx";
String id = UUID.randomUUID().toString();
ExcelList excelList = new ExcelList();
excelList.setId(id);
excelList.setName(name);
list.add(excelList);
// 异步导出
exportExcel.asyncExportExcel(id,name,startTime);
}
/**
* 获取导出列表 - 模拟
*/
@GetMapping("/excel/list")
public List<ExcelList> list() {
return list;
}
/**
* 文件下载
*/
@GetMapping("/excel/downLoad")
public void downLoad(HttpServletResponse response,@RequestParam String url) {
FileUtils.download(url, response);
}
}
2-3、异步下载实现
ExportExcel
注:使用异步注解@Async
需要先在启动类上开启 @EnableAsync
import org.springframework.scheduling.annotation.Async;
public interface ExportExcel {
/**
* 异步导出
* @param id 唯一记录Id
* @param name 文件名称
* @param startTime 下载开始时间
*/
@Async
void asyncExportExcel(String id,String name,Long startTime);
}
TestExportExcelImpl
@Service
public class TestExportExcelImpl implements ExportExcel {
@Override
public void asyncExportExcel(String id,String name,Long startTime) {
// 模拟查询数据过程
String[] header = new String[]{"姓名","年纪"};
String[] keys = new String[]{"name","age"};
List<Map<String, Object>> content = new ArrayList<>();
Map<String, Object> map1 = new HashMap<>();
map1.put("name","小道仙");
map1.put("age","23");
content.add(map1);
Map<String, Object> map2 = new HashMap<>();
map2.put("name","小道仙97");
map2.put("age","97");
content.add(map2);
try {
// 获取Excel导出文件流
ByteArrayOutputStream os = new ByteArrayOutputStream();
ExcelUtils.exportExcel(header,keys,content,"first",os);
byte[] content1 = os.toByteArray();
InputStream inputStream = new ByteArrayInputStream(content1);
// 上传文件 返回下载地址
String url = FileUtils.uploadInputStream(inputStream, name);
/**
* 找到当前数据并封装结果集
*
* 其实这里很简单并无这么复杂,实际情况我们只需要一个 update 语句就可以搞定
*/
for (ExcelList item : ExportExcelController.list) {
if (item.getId().equals(id)) {
item.setRows(content.size());
item.setDownloadUrl(url);
item.setTakeUpTime(System.currentTimeMillis() - startTime);
break;
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
三、演示
下面的演示的前提都是在启动了项目的基础上
3-1、导出
因为没有做任何的返回值,所以是空返回,这里也可以自定义任何提示返回。
http://127.0.0.1:8888/excel/export
3-2、下载列表
http://127.0.0.1:8888/excel/list
返回结果如下:
[
{
"id": "d3cb3551-cb33-445e-8e60-9534197f6647",
"name": "Excel异步导出测试80d50264-3930-4667-8bc5-2d4a1cfe0d9d.xlsx",
"rows": 2,
"takeUpTime": 5,
"downloadUrl": "2021/8/8/Excel异步导出测试80d50264-3930-4667-8bc5-2d4a1cfe0d9d.xlsx"
}
]
3-3、下载
http://127.0.0.1:8888/excel/downLoad?url=2021/8/8/Excel异步导出测试80d50264-3930-4667-8bc5-2d4a1cfe0d9d.xlsx
原文始发于微信公众号(小道仙97):通用异步导出Excel封装
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/41408.html