SpringBoot集成EasyExcel实现文件导入导出

news/2024/7/21 5:26:41 标签: spring boot, 后端, java, excel

 一、什么是EasyExcel

EasyExcel 是一款基于Java的开源Excel操作工具,它提供了简单且强大的 API,使开发人员可以轻松地读写、操作和生成Excel文件。

二、常用注解

  1. @ExcelProperty:用于标识实体类中的字段与 Excel 表格中的列的对应关系。

  2. @ExcelIgnore:用于标识在读写 Excel 时忽略某个字段。

  3. @ExcelIgnoreUnannotated:用于标识在读取 Excel 时忽略未标注 @ExcelProperty 注解的字段。

  4. @ExcelTable:用于标识表格的属性,如表头所在行数等。

三、SpringBoot整合

1.添加依赖

主要依赖:

java">        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.1.3</version>
        </dependency>

项目完整依赖:

java"><dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.2-jre</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.31</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.9</version>
        </dependency>
        <!-- mybatis-plus配置不同数据源 需要引入的包 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.16</version>
        </dependency>
    </dependencies>

2.实体类

java">@Data
public class Stu implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
 
    @ExcelProperty("姓名")
    private String name;
 
    @ExcelProperty("年龄")
    private Integer age;
 
    @ExcelProperty("班级")
    private String calss;
 
    @ExcelProperty("学校")
    private String school;
 
    @ExcelProperty(value = "性别")
    private Integer sex;
}

3.自定义监听器

java">/**
 * 自定义监听器,对下载的excel中的数据进行校验
 * */
public class StuListener extends AnalysisEventListener {
 
    List<String> names = new ArrayList<>();
 
    /**
     * 每解析一行,回调该方法
     *
     * @param data
     * @param context
     */
    @Override
    public void invoke(Object data, AnalysisContext context) {
        //校验名称
        String name = ((Stu) data).getName();
        if (StrUtil.isBlank(name)) {
            throw new RuntimeException(String.format("第%s行名称为空,请核实", context.readRowHolder().getRowIndex() + 1));
        }
        if (names.contains(name)) {
            throw new RuntimeException(String.format("第%s行名称已重复,请核实", context.readRowHolder().getRowIndex() + 1));
        } else {
            names.add(name);
        }
    }
 
    /**
     * 出现异常回调
     *
     * @param exception
     * @param context
     * @throws Exception
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        if (exception instanceof ExcelDataConvertException) {
            /**从0开始计算*/
            Integer columnIndex = ((ExcelDataConvertException) exception).getColumnIndex() + 1;
            Integer rowIndex = ((ExcelDataConvertException) exception).getRowIndex() + 1;
            String message = "第" + rowIndex + "行,第" + columnIndex + "列" + "数据格式有误,请核实";
            throw new RuntimeException(message);
        } else if (exception instanceof RuntimeException) {
            throw exception;
        } else {
            super.onException(exception, context);
        }
    }
 
    /**
     * 解析完,全部回调
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        //解析完,全部回调逻辑实现
        names.clear();
    }
}

4.导入

准备一个导入数据的文件,下方是我的文件:

Controller层代码

java">    @PostMapping(value = "/importData")
    public void importData(MultipartFile file) {
        try {
            //获取文件的输入流
            InputStream inputStream = file.getInputStream();
            List<Stu> lst = EasyExcel.read(inputStream) //调用read方法
                    //注册自定义监听器,字段校验可以在监听器内实现
                    .registerReadListener(new StuListener())
                    .head(Stu.class) //对应导入的实体类
                    .sheet(0) //导入数据的sheet页编号,0代表第一个sheet页,如果不填,则会导入所有sheet页的数据
                    .headRowNumber(1) //列表头行数,1代表列表头有1行,第二行开始为数据行
                    .doReadSync(); //开始读Excel,返回一个List<T>集合,继续后续入库操作

            System.out.println(lst);
            // TODO 导入后的处理逻辑

        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

导入成功

5.导出

Controller代码

java">
    /**
     * 导出数据
     * */
    @GetMapping("/export/user")
    public void exportUserExcel(HttpServletResponse response) throws IOException {
        OutputStream outputStream=response.getOutputStream();
        try {
            String filePath = "userlist.xlsx"; // 保存到当前项目下的文件名
            File file = new File(filePath);
            this.setExcelResponseProp(response, "用户列表");
            // 模拟根据条件在数据库查询数据
//            List<Stu> stus = stuMapper.selectList(null);
            List<Stu> stus = new ArrayList<>();

            for (int i = 0; i < 5; i++) {
                Stu stu = new Stu();
                stu.setId(i);
                stu.setName("老" + i);
                if (i % 2 == 0) {
                    stu.setSex(1);
                } else {
                    stu.setSex(0);
                }
                stu.setCalss(i + "班");
                stu.setSchool("第一中学");
                stus.add(stu);
            }

            // 创建本地文件输出流
            outputStream = new FileOutputStream(file);
            //这个实现方式非常简单直接,使用EasyExcel的write方法将查询到的数据进行处理,以流的形式写出即可
            EasyExcel.write(outputStream,Stu.class)//对应的导出实体类
                    .excelType(ExcelTypeEnum.XLSX)//excel文件类型,包括CSV、XLS、XLSX
                    .sheet("Stu列表")//导出sheet页名称
                    .doWrite(stus); //查询获取的数据集合List<T>,转成excel
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            outputStream.flush();
            outputStream.close();
        }
    }

    /**
     * 设置响应结果
     *
     * @param response    响应结果对象
     * @param rawFileName 文件名
     * @throws UnsupportedEncodingException 不支持编码异常
     */
    private void setExcelResponseProp(HttpServletResponse response, String rawFileName) throws UnsupportedEncodingException {

        //设置内容类型
        response.setContentType("application/vnd.vnd.ms-excel");
        //设置编码格式
        response.setCharacterEncoding("utf-8");
        //设置导出文件名称(避免乱码)
        String fileName = URLEncoder.encode(rawFileName.concat(".xlsx"), "UTF-8");
        // 设置响应头
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
    }

导出成功

以上一个简单的demo就编写完成了。


http://www.niftyadmin.cn/n/5408796.html

相关文章

《高性能MYSQL》-- 查询性能优化

查询性能优化 深刻地理解MySQL如何真正地执行查询&#xff0c;并明白高效和低效的原因何在 为什么查询速度会慢 查询的生命周期&#xff08;不完整&#xff09;&#xff1a;从客户端到服务器&#xff0c;然后服务器上进行语法解析&#xff0c;生成执行计划&#xff0c;执行&a…

如何使用 ArcGIS Pro 统计四川省各市道路长度

在某些时候&#xff0c;我们需要进行分区统计&#xff0c;如果挨个裁剪数据再统计&#xff0c;不仅步骤繁琐、耗时&#xff0c;还会产生一些多余的数据&#xff0c;这里教大家如何在不裁剪数据的情况下统计四川各市的道路长度&#xff0c;希望能对你有所帮助。 数据来源 教程…

10kV/35kV并网分布式光伏系统-实现错峰有序用电

根据国家电网 Q/GDW1480-2015 《分布式电源接入电网技术规定》&#xff1a;分布式电源并网电压等级可根据各 并网点装机容量进行初步选择&#xff0c;推荐如下&#xff1a; • 8kW 及以下可接入 220V &#xff1b; • 8kW~400kW 可接入 380V &#xff1b; • 400kW~60…

2.Zookeeper集成springboot操作节点,事件监听,分布式锁实现

1.Springboot项目中添加zookeeper 已经对应的客户端依赖 &#xff0c;pom.xml文件如下 <!-- Zookeeper组件 --><dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.9.1</version…

【每日一题】1976. 到达目的地的方案数-2024.3.5

题目: 1976. 到达目的地的方案数 你在一个城市里,城市由 n 个路口组成,路口编号为 0 到 n - 1 ,某些路口之间有 双向 道路。输入保证你可以从任意路口出发到达其他任意路口,且任意两个路口之间最多有一条路。 给你一个整数 n 和二维整数数组 roads ,其中 roads[i] = […

Git分布式管理-头歌实验分支管理

一、创建本地分支-git branch 任务描述 当你进入一个团队&#xff0c;在获得产品的完整代码之后&#xff0c;你首先要做的就是&#xff0c;在本地创建一个属于自己的分支&#xff0c;然后才能在自己的分支上进行开发。 本关任务&#xff1a;在本地仓库创建一个新的分支&#xf…

05-prometheus的联邦模式-分布式监控

一、联邦模式概述 1&#xff0c;架构介绍 由于&#xff0c;在大型企业中&#xff0c;被监控项目比较多&#xff0c;多到一台prometheus服务无法承载其大量的监控数据的传输&#xff0c;所以&#xff0c;联邦模式应运而生&#xff0c;它同等于zabbix监控的分布式&#xff0c;就…

专业的安全数据交换系统,如何进行网间数据安全交换?

网络隔离是企业网络安全管理的重要组成部分&#xff0c;它有助于提高网络的整体安全性&#xff0c;保护企业资产和客户数据&#xff0c;同时满足法规合规要求。很多企业为了防止内部核心数据泄露&#xff0c;都实施了网络隔离&#xff0c;比如划分成内网、外网&#xff0c;有的…