乐于分享
好东西不私藏

Spring Boot 3 的 EasyExcel 快速入门教程(已验证)

Spring Boot 3 的 EasyExcel 快速入门教程(已验证)

EasyExcel 是阿里开源的 Excel 处理工具,适合做:

  • Excel 导出
  • Excel 导入
  • 大数据量读写
  • 减少 Apache POI 的内存占用问题

这篇教程基于:

  • Spring Boot 3
  • JDK 17
  • Maven
  • 包名:com.example.springboot

实现两个最常见功能:

  • 导出 Excel
  • 导入 Excel

1. 项目结构

springboot-easyexcel-demo
├─ pom.xml
├─ src/main/java/com/example/springboot
│  ├─ SpringbootApplication.java
│  ├─ controller
│  │  └─ ExcelController.java
│  ├─ listener
│  │  └─ UserExcelListener.java
│  ├─ model
│  │  └─ UserExcelData.java
│  └─ service
│     └─ ExcelService.java
└─ src/main/resources
   └─ application.yml

2. 添加依赖

文件相对路径:pom.xml

<projectxmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         https://maven.apache.org/xsd/maven-4.0.0.xsd"
>


<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>

<groupId>com.example</groupId>
<artifactId>springboot-easyexcel-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-easyexcel-demo</name>
<description>Spring Boot 3 EasyExcel Demo</description>

<properties>
<java.version>17</java.version>
</properties>

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

<!-- EasyExcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>4.0.3</version>
</dependency>

<!-- lombok,可选 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

3. 启动类

文件相对路径:src/main/java/com/example/springboot/SpringbootApplication.java

package com.example.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
publicclassSpringbootApplication{

publicstaticvoidmain(String[] args){
        SpringApplication.run(SpringbootApplication.classargs);
    }
}

4. 定义 Excel 对应实体

这里定义导入导出都使用的对象。

文件相对路径:src/main/java/com/example/springboot/model/UserExcelData.java

package com.example.springboot.model;

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

@Data
publicclassUserExcelData{

@ExcelProperty("用户ID")
private Long id;

@ExcelProperty("用户名")
private String username;

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

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

说明:

  • @ExcelProperty("用户ID") 表示 Excel 表头名称
  • 字段顺序默认按类中属性顺序导出
  • 如果需要固定列顺序,可以额外配置 index

5. 编写导入监听器

EasyExcel 读 Excel 时通常使用监听器模式。

文件相对路径:src/main/java/com/example/springboot/listener/UserExcelListener.java

package com.example.springboot.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.example.springboot.model.UserExcelData;

import java.util.ArrayList;
import java.util.List;

publicclassUserExcelListenerimplementsReadListener<UserExcelData{

privatefinal List<UserExcelData> dataList = new ArrayList<>();

@Override
publicvoidinvoke(UserExcelData data, AnalysisContext context){
        dataList.add(data);
    }

@Override
publicvoiddoAfterAllAnalysed(AnalysisContext context){
        System.out.println("Excel读取完成,共 " + dataList.size() + " 条数据");
    }

public List<UserExcelData> getDataList(){
return dataList;
    }
}

6. 编写业务层

文件相对路径:src/main/java/com/example/springboot/service/ExcelService.java

package com.example.springboot.service;

import com.alibaba.excel.EasyExcel;
import com.example.springboot.listener.UserExcelListener;
import com.example.springboot.model.UserExcelData;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

@Service
publicclassExcelService{

publicvoidexportUsers(HttpServletResponse response)throws IOException {
        List<UserExcelData> userList = mockData();

        String fileName = URLEncoder.encode("用户数据", StandardCharsets.UTF_8)
                .replaceAll("\\+""%20");

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition",
"attachment;filename*=utf-8''" + fileName + ".xlsx");

        EasyExcel.write(response.getOutputStream(), UserExcelData.class)
                .sheet("用户列表")
                .doWrite(userList)
;
    }

public List<UserExcelData> importUsers(MultipartFile file)throws IOException {
        UserExcelListener listener = new UserExcelListener();

        EasyExcel.read(file.getInputStream(), UserExcelData.classlistener)
                .sheet()
                .doRead()
;

return listener.getDataList();
    }

private List<UserExcelData> mockData(){
        List<UserExcelData> list = new ArrayList<>();

        UserExcelData user1 = new UserExcelData();
        user1.setId(1L);
        user1.setUsername("张三");
        user1.setAge(20);
        user1.setEmail("zhangsan@example.com");
        list.add(user1);

        UserExcelData user2 = new UserExcelData();
        user2.setId(2L);
        user2.setUsername("李四");
        user2.setAge(25);
        user2.setEmail("lisi@example.com");
        list.add(user2);

return list;
    }
}

7. 编写控制器

文件相对路径:src/main/java/com/example/springboot/controller/ExcelController.java

package com.example.springboot.controller;

import com.example.springboot.model.UserExcelData;
import com.example.springboot.service.ExcelService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;

@RestController
@RequestMapping("/excel")
publicclassExcelController{

privatefinal ExcelService excelService;

publicExcelController(ExcelService excelService){
this.excelService = excelService;
    }

@GetMapping("/export")
publicvoidexport(HttpServletResponse response)throws IOException {
        excelService.exportUsers(response);
    }

@PostMapping("/import")
public List<UserExcelData> importExcel(MultipartFile file)throws IOException {
return excelService.importUsers(file);
    }
}

8. 配置文件

文件相对路径:src/main/resources/application.yml

server:
port:8080

spring:
servlet:
multipart:
max-file-size:10MB
max-request-size:10MB

9. 启动后如何测试

启动项目后:

9.1 导出 Excel

浏览器访问:

http://localhost:8080/excel/export

效果:

  • 自动下载一个 用户数据.xlsx
  • Sheet 名称为 用户列表

9.2 导入 Excel

接口地址:

POST http://localhost:8080/excel/import

使用 Postman 或 Apifox:

  • 请求方式:POST
  • Content-Type:multipart/form-data
  • 参数名:file
  • 上传一个 Excel 文件

Excel 表头示例:

用户ID | 用户名 | 年龄 | 邮箱
1     | 张三   | 20   | zhangsan@example.com
2     | 李四   | 25   | lisi@example.com

返回结果示例:

[
  {
"id"1,
"username""张三",
"age"20,
"email""zhangsan@example.com"
  },
  {
"id"2,
"username""李四",
"age"25,
"email""lisi@example.com"
  }
]

10. Spring Boot 3 下的注意事项

这是本篇最重要的部分。

10.1 javax 改成了 jakarta

Spring Boot 3 基于 Spring Framework 6,很多 Servlet 相关包已经从:

javax.servlet.http.HttpServletResponse

改成:

jakarta.servlet.http.HttpServletResponse

所以导出文件时一定要导入:

import jakarta.servlet.http.HttpServletResponse;

不要再写 javax.servlet.*


10.2 JDK 版本建议 17+

Spring Boot 3 最低要求 JDK 17,因此项目里建议直接使用:

  • JDK 17
  • Spring Boot 3.x
  • EasyExcel 4.x

10.3 导出时注意响应头

如果文件名包含中文,建议这样处理:

String fileName = URLEncoder.encode("用户数据", StandardCharsets.UTF_8)
        .replaceAll("\\+""%20");

否则下载后的文件名可能乱码。


10.4 不要一次性把超大文件全部放内存

虽然 EasyExcel 比 POI 更省内存,但如果你在监听器里把所有数据都放进 List,大文件仍然会占用很多内存。

更合理的做法是:

  • 每读取一批数据就入库
  • 分批处理
  • 不要所有数据都堆在内存里

比如生产环境中通常会这样做:

  • 读取 1000 条
  • 批量保存数据库
  • 清空缓存
  • 继续读取

10.5 表头必须和实体注解匹配

如果 Excel 表头写的是:

用户名称

但你的代码是:

@ExcelProperty("用户名")
private String username;

那么这个字段可能读不到值。

所以导入时要确保:

  • 表头文字一致
  • 列顺序尽量稳定
  • 字段类型正确

10.6 日期、数字格式要提前约定

实际项目中 Excel 常见问题:

  • 日期列格式混乱
  • 数字变成科学计数法
  • 手机号前导 0 丢失

建议:

  • 手机号、身份证号用字符串接收
  • 日期统一格式
  • 模板先固定好

11. 生产环境常见优化建议

如果你要把这套代码用于实际项目,建议补充:

  • 导入参数校验
  • 空文件校验
  • 文件类型校验
  • 异常处理
  • 批量入库
  • 导入失败结果反馈
  • 下载模板接口

例如导入接口可以先校验:

if (file == null || file.isEmpty()) {
thrownew IllegalArgumentException("上传文件不能为空");
}

还可以限制只允许上传:

  • .xls
  • .xlsx

12. 总结

在 Spring Boot 3 中集成 EasyExcel 并不复杂,核心步骤只有 4 个:

  1. 引入 EasyExcel 依赖
  2. 定义 Excel 映射实体
  3. 使用 EasyExcel.write() 导出
  4. 使用 EasyExcel.read() + Listener 导入

最需要注意的是:

  1. Spring Boot 3 使用 jakarta.servlet
  2. 中文文件名要处理编码
  3. 大文件导入不要一次性全部放内存
  4. Excel 表头要和 @ExcelProperty 对应