使用 EasyExcel 轻松实现 Java Excel 导入导出:从入门到实战

在企业级应用开发中,Excel 文件的导入导出是非常常见的需求。传统的 POI 框架虽然功能强大,但 API 复杂且对大数据量处理不够友好。阿里巴巴开源的 EasyExcel 框架基于 POI 进行了高度封装,提供了更简洁的 API 和更高效的内存管理,尤其适合处理大规模数据。本文将通过一个完整的 Spring Boot 项目,详细讲解如何使用 EasyExcel 实现 Excel 的导入导出功能。

一、开发环境准备

1. 技术栈选择

  • Java 8+:主流开发语言
  • Spring Boot 2.7.5:快速构建 Java 应用
  • EasyExcel 3.1.1:轻量级 Excel 处理框架
  • Lombok:简化 JavaBean 开发

2. Maven 依赖配置

在pom.xml中添加核心依赖:

<dependencies>    <!-- Spring Boot Web -->    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-web</artifactId>    </dependency>        <!-- EasyExcel核心库 -->    <dependency>        <groupId>com.alibaba</groupId>        <artifactId>easyexcel</artifactId>        <version>3.1.1</version>    </dependency>        <!-- Lombok注解 -->    <dependency>        <groupId>org.projectlombok</groupId>        <artifactId>lombok</artifactId>        <optional>true</optional>    </dependency></dependencies>

二、核心功能实现

1. 定义数据实体类

创建Student实体类,通过 EasyExcel 注解配置字段映射和表头样式:

@Data@AllArgsConstructor@NoArgsConstructorpublic class Student {    // 表头名称为"学号",列宽20    @ExcelProperty(value = "学号", index = 0)    @ColumnWidth(20)    private Long studentId;        // 表头名称为"姓名",列宽15    @ExcelProperty(value = "姓名", index = 1)    @ColumnWidth(15)    private String studentName;        // 表头名称为"年龄",指定格式转换器    @ExcelProperty(value = "年龄", index = 2)    private Integer age;        // 忽略该字段,不参与Excel读写    @ExcelIgnore    private String remark;}

2. 实现数据监听器(导入功能)

通过流式读取处理大数据量,避免内存溢出:

public class StudentDataListener extends AnalysisEventListener<Student> {    private List<Student> studentList = new ArrayList<>();        // 逐行读取时调用    @Override    public void invoke(Student student, AnalysisContext context) {        studentList.add(student);        // 每5000条数据批量处理(可根据需求调整)        if (studentList.size() >= 5000) {            saveData(studentList);            studentList.clear();        }    }    // 所有数据读取完成后调用    @Override    public void doAfterAllAnalysed(AnalysisContext context) {        saveData(studentList); // 处理剩余数据    }    private void saveData(List<Student> data) {        // 这里可以替换为实际的数据库批量插入操作        System.out.println("批量处理数据,数据量:" + data.size());    }}

3. 封装业务服务类

实现 Excel 导出的核心逻辑,支持普通导出和带样式导出:

@Servicepublic class ExcelService {        // 简单导出(默认样式)    public void exportSimpleExcel(HttpServletResponse response) throws IOException {        List<Student> dataList = generateTestData(); // 生成测试数据                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");        response.setCharacterEncoding("utf-8");        String fileName = URLEncoder.encode("学生信息表", "UTF-8").replaceAll("\\+", "%20");        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");                EasyExcel.write(response.getOutputStream(), Student.class).sheet("学生列表").doWrite(dataList);    }    // 复杂导出(自定义样式)    public void exportStyledExcel(HttpServletResponse response) throws IOException {        List<Student> dataList = generateTestData();                // 配置标题样式        WriteCellStyle headCellStyle = new WriteCellStyle();        headCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());                // 配置内容样式        WriteCellStyle contentCellStyle = new WriteCellStyle();        contentCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);                // 注册样式策略        HorizontalCellStyleStrategy styleStrategy =             new HorizontalCellStyleStrategy(headCellStyle, contentCellStyle);                EasyExcel.write(response.getOutputStream(), Student.class)            .registerWriteHandler(styleStrategy)            .sheet("学生列表")            .doWrite(dataList);    }    // 导入功能核心方法    public void importExcel(MultipartFile file) throws IOException {        EasyExcel.read(file.getInputStream(), Student.class, new StudentDataListener()).sheet().doRead();    }    private List<Student> generateTestData() {        // 生成100条测试数据(可根据需要扩展)        List<Student> dataList = new ArrayList<>();        for (int i = 1; i <= 100; i++) {            dataList.add(new Student((long) i, "学生" + i, 18 + i % 5));        }        return dataList;    }}

4. 创建控制器接口

提供 RESTful 接口实现功能调用:

@RestController@RequestMapping("/excel")public class ExcelController {        @Resource    private ExcelService excelService;    // 简单导出接口    @GetMapping("/export/simple")    public void exportSimpleExcel(HttpServletResponse response) throws IOException {        excelService.exportSimpleExcel(response);    }    // 带样式导出接口    @GetMapping("/export/styled")    public void exportStyledExcel(HttpServletResponse response) throws IOException {        excelService.exportStyledExcel(response);    }    // 导入接口    @PostMapping("/import")    public String importExcel(@RequestParam("file") MultipartFile file) {        try {            excelService.importExcel(file);            return "导入成功";        } catch (Exception e) {            return "导入失败:" + e.getMessage();        }    }}

三、项目核心特性解析

1. 高效的内存管理

  • 流式处理:采用 SAX 模式逐行读取,内存占用低(处理 10 万条数据仅需约 100MB 内存)
  • 批量处理:通过数据监听器实现分批数据持久化,避免单次处理数据量过大

2. 灵活的注解配置

注解

功能说明

示例用法

@ExcelProperty

字段与表头映射,支持索引或名称

@ExcelProperty("学号")

@ColumnWidth

自定义列宽

@ColumnWidth(20)

@ExcelIgnore

忽略字段

@ExcelIgnore

@DateTimeFormat

日期格式转换

@DateTimeFormat("yyyy-MM-dd")

@NumberFormat

数字格式转换

@NumberFormat("#.##")

3. 完善的异常处理

  • 文件格式校验:自动识别 Excel 2003/2007 格式
  • 类型转换异常:支持自定义异常处理器
  • 内存溢出保护:通过数据分片策略避免 OOM

四、功能测试验证

1. 导出功能测试

  • 使用 Postman 发送 GET 请求到/excel/export/simple,浏览器会自动下载 Excel 文件
  • 带样式导出接口/excel/export/styled会生成带灰色表头和居中对齐的表格

2. 导入功能测试

  • 通过表单上传 Excel 文件(需符合 Student 实体类字段要求),成功后返回 "导入成功"
  • 支持批量处理最大 10 万条数据(可通过AnalysisContext配置调整批次大小)

五、总结与最佳实践

1. 适用场景

  • 大数据量 Excel 处理(建议单文件不超过 50MB)
  • 复杂表头格式配置
  • 高性能要求的批量导入导出

2. 优化建议

  • 数据校验:在数据监听器中添加字段合法性校验
  • 日志记录:对导入导出操作添加完整的日志跟踪
  • 事务管理:在批量数据持久化时添加数据库事务
  • 文件存储:支持本地文件系统、云存储等多种存储方式

3. 开源生态

EasyExcel 提供了丰富的扩展能力:

  • 支持自定义转换器(Converter接口)
  • 灵活的写入处理器(WriteHandler接口)
  • 集成 Spring Boot 实现自动配置

通过本文的实战案例,我们展示了如何利用 EasyExcel 简化 Excel 操作,实现高效的导入导出功能。相比传统 POI 框架,EasyExcel 在代码简洁性和性能上都有明显优势,尤其适合企业级应用开发。完整的项目代码可以在GitHub 仓库获取,欢迎 Star 和 Fork。

如果在实际开发中遇到复杂格式处理或性能优化问题,建议参考官方文档(EasyExcel 官方文档)或加入技术交流群,获取更多最佳实践。