欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Springboot导出excel文件并下载

程序员文章站 2022-10-03 11:08:29
Springboot导出excel文件并下载文章目录Springboot导出excel文件并下载前言一、引入Maven包?二、数据库查询数据2.1 实体类2.2 mapper三、导出代码四、 补充4.1 问题4.2 方案4.3 建议前言在项目中,我们难免遇到需要导出的数据,而数据一般来说都是具有一定商业价值的东西,并不是每个员工都能导出的,所以不能使用前端js导出,也不是说不能,而是如果使用js导出有两个明显得不足,你得先去判断一下该用户是否有导出的权限js导出excel的原理是捕捉页面...

Springboot导出excel文件并下载



前言

在项目中,我们难免遇到需要导出的数据,而数据一般来说都是具有一定商业价值的东西,并不是每个员工都能导出的,所以不能使用前端js导出,也不是说不能,而是如果使用js导出有两个明显得不足,

  1. 你得先去判断一下该用户是否有导出的权限
  2. 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 建议

  1. 异步下载!异步!异步!异步!
  2. 如果对样式没什么要求,也不用公式的话,强烈推荐导出CSV格式
  3. 可以采用多线程的方式,先查总数,然后分一下看需要多少个线程,每个线程读取一部数据并写入单独Excel文件; 当然,也可以多线程读,单线程写
  4. 分批导,这一点跟上一步类似

本文地址:https://blog.csdn.net/qq_41566219/article/details/109626617

相关标签: java