Springboot导出excel文件并下载
程序员文章站
2022-05-03 23:41:45
Springboot导出excel文件并下载文章目录Springboot导出excel文件并下载前言一、引入Maven包?二、数据库查询数据2.1 实体类2.2 mapper三、导出代码四、 补充4.1 问题4.2 方案4.3 建议前言在项目中,我们难免遇到需要导出的数据,而数据一般来说都是具有一定商业价值的东西,并不是每个员工都能导出的,所以不能使用前端js导出,也不是说不能,而是如果使用js导出有两个明显得不足,你得先去判断一下该用户是否有导出的权限js导出excel的原理是捕捉页面...
Springboot导出excel文件并下载
文章目录
前言
在项目中,我们难免遇到需要导出的数据,而数据一般来说都是具有一定商业价值的东西,并不是每个员工都能导出的,所以不能使用前端js导出,也不是说不能,而是如果使用js导出有两个明显得不足,
- 你得先去判断一下该用户是否有导出的权限
- js导出excel的原理是捕捉页面的数据,所以有些页面没有显示的数据,就无法导出
综上所述,我们还是使用后端导出文件来的很好。
一、引入Maven包?
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-excelant</artifactId>
<version>3.12</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.12</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.8</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
二、数据库查询数据
2.1 实体类
@TableName("jms_flow_content")
@Getter
@Setter
public class JmsFlowContentEntity {
@TableField("id")
private Integer id;
@TableField("name")
private String name;
@TableField("content")
private String content;
@TableField("video")
private Integer video;
@TableField("state")
private Integer state;
@TableField("create_time")
private String createTime;
@TableField("update_time")
private String updateTime;
}
2.2 mapper
@Mapper
public interface JmsFlowContentMapper extends BaseMapper<JmsFlowContentEntity> {
}
我这边使用的是mybatis-plus,有兴趣的可以去学一下,如果不会的,可以按照自己熟悉的方式,mapper→xml→entity的方式获取数据
三、导出代码
这是一个serviceImpl
@Resource
private JmsFlowContentMapper jmsFlowContentMapper;
public void testHSSF() throws Exception {
// 1. 创建一个工作簿
HSSFWorkbook wb = new HSSFWorkbook();
// 2. 创建一个工作表
HSSFSheet sheet = wb.createSheet();
// 3. 获取数据库数据
List<JmsFlowContentEntity> jmsFlowContentEntities = jmsFlowContentMapper.selectList(null);
for (int i = 0; i < jmsFlowContentEntities.size(); i++) {
// 4. 创建行
HSSFRow row = sheet.createRow(i);
// 5. 使用反射获取实体的元素的总量
Class<? extends JmsFlowContentEntity> aClass = jmsFlowContentEntities.get(i).getClass();
Field[] fields = aClass.getDeclaredFields();
// 6. 行内单元格赋值
for (int j = 0; j < fields.length; j++) {
Field f = fields[j];
f.setAccessible(true);
HSSFCell cell = row.createCell(j);
cell.setCellValue(String.valueOf(f.get(jmsFlowContentEntities.get(i))));
}
}
// 7.写文件
FileOutputStream fos = new FileOutputStream("C:/Users/Admin/Desktop/"+System.currentTimeMillis()+".xls");
// 8.关闭流
wb.write(fos);
fos.close();
}
然后你自己写一个controller引用一下这个方法,就可以了。
大功告成!
四、 补充
4.1 问题
当数据量小(比如,几千几万条)的时候可以采用同步的方式,不用考虑别的。
而当数据量大的时候(比如,几十上百万)的时候问题就暴露出来了。
首先,慢是肯定的了。少则几十秒,多则几十分钟都是有可能的。
这还是小问题,最要命的因为一个导出把系统搞挂了。。。
笔者曾经见过,因为一个导出,系统直接挂了,还严重拖慢了同一台机器上的其它应用,最终宕机了。。。
究其原因,大量数据堆积在内存中,可能会造成内存溢出。夸张一点,几百万条数据每条数据几十个字段都放到内存中,要等到全部写完这些内存才会释放。
4.2 方案
- 针对单个工作表(sheet)的行数限制,可以分多个工作表
- 针对单个文件太大不容易打开,可以分多个文件,最终打成压缩包
- 针对内存溢出,可以分批导,每次导一批数据,分多次导
4.3 建议
- 异步下载!异步!异步!异步!
- 如果对样式没什么要求,也不用公式的话,强烈推荐导出CSV格式
- 可以采用多线程的方式,先查总数,然后分一下看需要多少个线程,每个线程读取一部数据并写入单独Excel文件; 当然,也可以多线程读,单线程写
- 分批导,这一点跟上一步类似
本文地址:https://blog.csdn.net/qq_41566219/article/details/109626617
上一篇: 使用 ArrayList.add() 方法,添加的数据为什么会被覆盖?
下一篇: 鱼和鸡蛋能一起吃吗