Java SpringBoot使用EasyExcel导入导出Excel文件

点击下载《Java SpringBoot使用EasyExcel导入导出Excel文件(源代码)》

在 Java Spring Boot 项目中,导入(读取)和导出(写入) Excel 文件是一项常见的需求。EasyExcel 是阿里巴巴开源的一个用于简化 Java 环境下 Excel 文件读取和写入操作的库。相比于传统的 Apache POI,EasyExcel 在性能和易用性方面进行了优化,特别适用于处理大规模 Excel 文件。

1. EasyExcel 介绍

1.1 EasyExcel 的特点

特性/方面 详细说明
基于事件驱动的解析 采用 SAX 解析方式,通过事件驱动逐行读取 Excel 数据,避免将整个文件加载到内存中,降低内存消耗。
内存友好 由于逐行读取和处理数据,内存占用极低,适合处理大型 Excel 文件,避免内存溢出问题。
简洁易用的 API 提供高度封装的 API,通过注解(如 @ExcelProperty)轻松实现 Java 对象与 Excel 列的映射,减少样板代码的编写。
支持多种数据格式 支持常见的 Excel 数据格式,包括 .xlsx.xls 文件,并支持自定义数据格式转换。
丰富的功能 支持读取和写入 Excel 文件、自定义转换器、多工作表操作、注解支持、异常处理等。
高性能 在处理大规模数据时表现出色,能够显著提高数据导入和导出的效率。
社区活跃 作为阿里巴巴开源项目,拥有活跃的社区和及时的更新,能够及时修复问题和添加新功能。
依赖其他库 依赖于 cglib 和其他一些库,如果项目中已经使用了不同版本的这些库,可能会导致版本冲突。
学习曲线 虽然 API 简洁,但对于不熟悉事件驱动编程或注解映射的开发者,可能需要一定的学习成本。
功能相对有限 与 Apache POI 相比,EasyExcel 对公式、图表、样式等复杂功能的支持相对较少。
灵活性高 支持自定义数据转换器、多工作表操作等功能,提供了高度的灵活性以满足不同的业务需求。

1.2 EasyExcel 的优点

优点 详细说明
内存效率高 采用事件驱动和逐行读取的方式,内存占用低,适合处理大型 Excel 文件,避免内存溢出问题。
性能优越 在处理大规模数据时具有更高的性能,能够显著减少处理时间,提高数据导入和导出效率。
易用性强 通过简洁的 API 和注解支持,简化了 Excel 数据的读取和写入操作,减少了代码量,提高了开发效率。
灵活性高 支持自定义数据转换器、多工作表操作等功能,能够满足不同的业务需求。
社区支持 作为开源项目,拥有活跃的社区和及时的更新,能够及时响应用户需求和问题。

1.3 EasyExcel 的缺点

缺点 详细说明
功能相对有限 与 Apache POI 相比,EasyExcel 对公式、图表、样式等复杂功能的支持较少。
依赖其他库 依赖于 cglib 和其他一些库,可能导致版本冲突,需要注意依赖管理。
学习曲线 对于不熟悉事件驱动编程或注解映射的开发者,可能需要一定的学习成本。
社区规模 虽然拥有活跃的社区,但与 Apache POI 相比,社区规模相对较小,可能在某些情况下获取帮助的渠道相对有限。

2. EasyExcel使用

2.1 引入 EasyExcel 依赖

首先,需要在 pom.xml 中引入 EasyExcel 的依赖:

xml 复制代码
<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- EasyExcel 依赖 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>easyexcel-core</artifactId>
        <version>3.1.2</version>
    </dependency>

    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.3.0</version> <!-- 请检查最新版本 -->
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.24</version>
    </dependency>

    <!-- 其他依赖 -->
</dependencies>

2.2 定义数据模型

使用 EasyExcel 导入导出数据时,需要定义与 Excel 列对应的 Java 类,并使用注解标注列信息。

java 复制代码
package com.yyqq.exceldemo.model;

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

@Data
public class UserData {

    @ExcelProperty("编号") // Excel 中的列名
    private Integer id;

    @ExcelProperty("姓名")
    private String name;

    @ExcelProperty("年龄")
    private Integer age;

    @ExcelProperty("邮箱")
    private String email;
}

说明

  • @Data:Lombok 提供的注解,用于自动生成 getter、setter、toString 等方法。
  • @ExcelProperty:指定 Excel 中对应的列名。

2.3 Excel 导入导出Controller类

java 复制代码
package com.yyqq.exceldemo.controller;

import com.alibaba.excel.EasyExcel;
import com.yyqq.exceldemo.model.UserData;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@RestController
public class ExcelController {

    /**
     * 导入execl文件
     */
    @GetMapping("/export")
    public ResponseEntity<byte[]> exportExcel() {
        String fileName = "用户数据.xlsx";
        List<UserData> userList = generateUserData();

        // EasyExcel 写入到字节数组
        byte[] bytes = exportToExcel(userList);

        // 设置响应头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", fileName);

        return ResponseEntity.ok()
                .headers(headers)
                .body(bytes);
    }

    @PostMapping("/import")
    public String importExcel(@RequestParam("file") MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            // 使用 EasyExcel 读取 Excel 数据
            List<UserData> userList = EasyExcel.read(inputStream)
                    .head(UserData.class)
                    .sheet()
                    .doReadSync();

            // 处理导入的数据,例如保存到数据库
            processUserData(userList);

            return "导入成功,共导入 " + userList.size() + " 条数据";
        } catch (Exception e) {
            e.printStackTrace();
            return "导入失败: " + e.getMessage();
        }
    }

    /**
     * 模拟生产用户数据
     * @return
     */
    private List<UserData> generateUserData() {
        List<UserData> list = new ArrayList<>();
        for (int i = 1; i <= 100; i++) {
            UserData user = new UserData();
            user.setId(i);
            user.setName("用户" + i);
            user.setAge(20 + i % 30);
            user.setEmail("user" + i + "@example.com");
            list.add(user);
        }
        return list;
    }

    /**
     * 将数据导出至byte数组中
     */
    private byte[] exportToExcel(List<UserData> userList) {
        // 使用 EasyExcel 写入 Excel 到字节数组
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        EasyExcel.write(out, UserData.class)
                .sheet("用户数据")
                .doWrite(userList);
        return out.toByteArray();
    }

    /**
     * 导入数据方法
     */
    private List<UserData> importFromExcelWithPOI(MultipartFile file) {
        List<UserData> userList = new ArrayList<>();
        try (InputStream inputStream = file.getInputStream();
             Workbook workbook = WorkbookFactory.create(inputStream)) {
            Sheet sheet = workbook.getSheetAt(0);
            Iterator<Row> iterator = sheet.iterator();

            // 跳过表头
            if (iterator.hasNext()) {
                iterator.next();
            }

            while (iterator.hasNext()) {
                Row row = iterator.next();
                UserData user = new UserData();
                user.setId((int) row.getCell(0).getNumericCellValue());
                user.setName(row.getCell(1).getStringCellValue());
                user.setAge((int) row.getCell(2).getNumericCellValue());
                user.setEmail(row.getCell(3).getStringCellValue());
                userList.add(user);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return userList;
    }

    private void processUserData(List<UserData> userList) {
        // 这里可以添加将数据保存到数据库的逻辑
        // 例如使用 JPA 或 MyBatis 等持久层框架
        userList.forEach(user -> {
            // 模拟保存操作
            System.out.println("保存用户: " + user);
        });
    }
}

2.4 编写测试html文件

在src/main/resources/static目录创建import.html文件,代码如下:

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>Excel 导入</title>
</head>
<body>
<h1>导入 Excel 文件</h1>
<form method="POST" enctype="multipart/form-data" action="/import">
    <input type="file" name="file" accept=".xlsx, .xls" />
    <button type="submit">上传</button>
</form>
</body>
</html>

export导出接口说明

  • 导出接口/export 接口返回 Excel 文件。
  • generateUserData() 方法:生成示例用户数据。
  • exportToExcel() 方法
    • 使用 EasyExcel 的 write 方法将数据写入 ByteArrayOutputStream
    • sheet("用户数据") 指定工作表名称。
    • doWrite(userList) 写入数据列表。
  • 启动 Spring Boot 应用后,访问 http://localhost:8080/export,即可下载生成的 Excel 文件。

import导入接口说明

  • 导入接口/import 接口接收 Excel 文件并处理。
  • 导入逻辑
    • 使用 EasyExcel 的 read 方法读取上传的 Excel 文件。
    • head(UserData.class) 指定数据模型类。
    • sheet() 指定读取的工作表。
    • doReadSync() 同步读取数据。
  • processUserData() 方法:处理导入的数据,例如保存到数据库。
  • 使用Postman调用接口
  • 或者直接在浏览器中输入地址:http://127.0.0.1:8080/import.html,然后上传一个excel文件:

    结果如下:

3. 总结

EasyExcel 是一个高性能、易用性强的 Java 库,适用于处理大规模 Excel 文件的导入和导出操作。其基于事件驱动的解析方式、内存友好的特性以及简洁的 API 使得开发者能够高效地完成数据处理任务。然而,在需要处理复杂 Excel 功能(如公式、图表、样式等)时,EasyExcel 的功能可能相对有限。对于大多数常见的 Excel 操作需求,EasyExcel 是一个非常不错的选择,但在特定场景下,可能需要结合使用其他库或工具。

点击下载《Java SpringBoot使用EasyExcel导入导出Excel文件(源代码)》

相关推荐
程序员岳焱9 分钟前
15.Java 泛型编程:类型安全与代码复用
java·后端·编程语言
天天摸鱼的java工程师15 分钟前
摸鱼学 Spring:Bean 的生命周期,面试官为啥总揪着问?
java·后端·面试
比特森林探险记16 分钟前
MySQL 时间类型与 Java 日期时间类对应关系详解
java·后端
Channing Lewis32 分钟前
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
excel
小吕学编程32 分钟前
Apache POI操作Excel详解
java·excel
gb421528740 分钟前
springboot项目下面的单元测试注入的RedisConnectionFactory类redisConnectionFactory值为什么为空呢?
spring boot·后端·单元测试
Cynthia-石头1 小时前
docker镜像下载到本地,并导入服务器
java·开发语言·eureka
Seven971 小时前
算法题:数组中的第k个最大元素
java·leetcode
huangyujun99201231 小时前
设计模式杂谈-模板设计模式
java·设计模式
残*影1 小时前
Spring 中注入 Bean 有几种方式?
java·后端·spring