# SpringBoot集成EasyExcel企业级实战教程
本文将从零开始,基于IDEA 2023 Ultimate版搭建企业级SpringBoot-EasyExcel项目,完整实现Excel导入导出的核心功能,包含通用工具类封装、数据校验、多sheet导出等企业级特性,适配JDK 17和SpringBoot 3.5.10版本。
# 1. 开发环境准备
企业级开发中环境一致性是项目稳定运行的基础,首先需确认本地环境符合以下要求:
环境清单
- IDE:IntelliJ IDEA 2023 Ultimate版
- JDK:17
- Maven:3.9.4
- SpringBoot:3.5.10
- EasyExcel:3.3.2(适配JDK17和SpringBoot3的稳定版本)
# 2. 项目初始化
按照企业级规范创建项目,确保项目名称、包名符合要求:
# 2.1 新建SpringBoot项目

# 2.2 企业级项目结构规划
创建完成后,手动补充企业级项目的标准包结构,确保代码分层清晰:
SpringBoot-EasyExcel
├── src
│ ├── main
│ │ ├── java
│ │ │ └── cc
│ │ │ └── hep
│ │ │ ├── SpringBootEasyExcelApplication.java // 启动类
│ │ │ ├── common // 通用模块(返回结果、常量等)
│ │ │ ├── entity // 实体类(Excel DTO、业务实体)
│ │ │ ├── exception // 全局异常处理
│ │ │ ├── listener // EasyExcel导入监听器
│ │ │ ├── service // 业务层(接口+实现)
│ │ │ │ ├── impl
│ │ │ ├── util // 工具类(EasyExcel通用工具)
│ │ │ └── controller // 接口层
│ │ └── resources
│ │ ├── application.yml // 配置文件
│ └── test
│ └── java
│ └── cc
│ └── hep
│ └── SpringBootEasyExcelApplicationTests.java
└── pom.xml
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 3. 引入核心依赖
在pom.xml中添加EasyExcel及企业级开发常用依赖,注意版本兼容性:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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.5.10</version>
<relativePath/>
</parent>
<groupId>cc.hep</groupId>
<artifactId>SpringBoot-EasyExcel</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringBoot-EasyExcel</name>
<description>SpringBoot集成EasyExcel企业级实战项目</description>
<properties>
<java.version>17</java.version>
<easyexcel.version>3.3.2</easyexcel.version>
</properties>
<dependencies>
<!-- SpringWeb核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- EasyExcel核心依赖(适配JDK17/SpringBoot3) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.version}</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>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
依赖添加完成后,点击IDEA的「Reload All Maven Projects」刷新依赖,确保无下载错误。
# 4. 企业级基础架构搭建
企业级项目需统一接口返回格式、全局处理异常,避免接口格式混乱和重复的异常捕获逻辑。
# 4.1 通用返回结果类
在cc.hep.common包下创建Result.java,统一所有接口的返回格式:
package cc.hep.common;
import lombok.Data;
/**
* 企业级通用返回结果类
* 所有接口统一返回该格式,便于前端解析
*/
@Data
public class Result<T> {
/**
* 状态码:200成功,500失败,400参数错误
*/
private Integer code;
/**
* 提示信息
*/
private String msg;
/**
* 业务数据
*/
private T data;
// 私有构造,禁止外部直接创建
private Result() {}
// 成功返回(无数据)
public static <T> Result<T> success() {
Result<T> result = new Result<>();
result.setCode(200);
result.setMsg("操作成功");
return result;
}
// 成功返回(带数据)
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(200);
result.setMsg("操作成功");
result.setData(data);
return result;
}
// 失败返回
public static <T> Result<T> fail(String msg) {
Result<T> result = new Result<>();
result.setCode(500);
result.setMsg(msg);
return result;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 4.2 全局异常处理器
在cc.hep.exception包下创建GlobalExceptionHandler.java,统一捕获项目异常:
package cc.hep.exception;
import cc.hep.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理器
* 捕获所有未处理的异常,统一返回格式
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 捕获运行时异常
*/
@ExceptionHandler(RuntimeException.class)
public Result<?> handleRuntimeException(RuntimeException e) {
log.error("运行时异常:", e);
return Result.fail("系统异常:" + e.getMessage());
}
/**
* 捕获EasyExcel专属异常
*/
// 尝试更换一种捕获方式,捕获更通用的 AnalysisException
@ExceptionHandler(com.alibaba.excel.exception.ExcelAnalysisException.class)
public Result<?> handleExcelAnalysisException(com.alibaba.excel.exception.ExcelAnalysisException e) {
log.error("Excel解析异常:", e);
return Result.fail("Excel解析失败:" + e.getMessage());
}
/**
* 捕获所有未知异常
*/
@ExceptionHandler(Exception.class)
public Result<?> handleException(Exception e) {
log.error("未知异常:", e);
return Result.fail("服务器内部错误,请联系管理员");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 4.3 基础配置文件
在resources目录下创建application.yml,配置文件上传大小限制(企业级必备):
spring:
servlet:
multipart:
max-file-size: 10MB # 单个文件最大10MB
max-request-size: 100MB # 单次请求最大100MB
server:
port: 8080 # 项目端口
2
3
4
5
6
7
# 5. EasyExcel核心实体设计
EasyExcel通过注解映射Excel列与实体字段,企业级开发需设计规范的Excel DTO,支持复杂表头、格式校验等特性。
# 5.1 业务实体(用户信息)
在cc.hep.entity包下创建User.java(业务核心实体):
package cc.hep.entity;
import lombok.Data;
import java.util.Date;
/**
* 业务实体:用户信息
* 对应数据库表结构(企业级中需添加JPA/MyBatis注解)
*/
@Data
public class User {
private Long id; // 用户ID
private String username; // 用户名
private String realName; // 真实姓名
private Integer age; // 年龄
private String phone; // 手机号
private Date createTime; // 创建时间
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 5.2 Excel导入导出DTO
在cc.hep.entity包下创建UserExcelDTO.java(专门用于Excel交互):
package cc.hep.entity;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.util.Date;
/**
* Excel导入导出DTO:用户信息
* 包含复杂表头、列宽、日期格式化等企业级配置
*/
@Data
@HeadRowHeight(20) // 表头行高
public class UserExcelDTO {
/**
* 用户名 - 复杂表头:用户信息→用户名
*/
@ExcelProperty(value = {"用户信息", "用户名"}, index = 0)
@ColumnWidth(20) // 列宽
private String username;
/**
* 真实姓名 - 复杂表头:用户信息→真实姓名
*/
@ExcelProperty(value = {"用户信息", "真实姓名"}, index = 1)
@ColumnWidth(20)
private String realName;
/**
* 年龄 - 复杂表头:用户信息→年龄
*/
@ExcelProperty(value = {"用户信息", "年龄"}, index = 2)
@ColumnWidth(10)
private Integer age;
/**
* 手机号 - 复杂表头:用户信息→手机号
*/
@ExcelProperty(value = {"用户信息", "手机号"}, index = 3)
@ColumnWidth(20)
private String phone;
/**
* 创建时间 - 复杂表头:用户信息→创建时间,日期格式化
*/
@ExcelProperty(value = {"用户信息", "创建时间"}, index = 4)
@ColumnWidth(25)
@DateTimeFormat("yyyy-MM-dd HH:mm:ss") // 日期格式化
private Date createTime;
/**
* 用户ID - Excel中忽略(仅业务逻辑使用)
*/
@ExcelIgnore
private Long id;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# 6. EasyExcel通用工具类封装
企业级开发中,封装通用工具类可大幅减少重复代码,这里实现支持单/多sheet导出、文件导入的通用工具。
在cc.hep.util包下创建EasyExcelUtil.java:
package cc.hep.util;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* EasyExcel通用工具类
* 封装企业级常用的Excel导入导出方法
*/
@Slf4j
public class EasyExcelUtil {
/**
* 单sheet Excel导出(直接下载)
* @param response 响应对象
* @param fileName 导出文件名(不带.xlsx)
* @param sheetName sheet名称
* @param clazz Excel实体类Class
* @param data 导出数据
* @param <T> 泛型
*/
public static <T> void exportExcel(HttpServletResponse response, String fileName,
String sheetName, Class<T> clazz, List<T> data) {
try {
// 设置响应头,解决中文文件名乱码
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8)
.replaceAll("\\+", "%20");
response.setHeader("Content-Disposition",
"attachment;filename*=utf-8''" + encodedFileName + ".xlsx");
// 写入Excel并输出到响应流
EasyExcel.write(response.getOutputStream(), clazz)
.sheet(sheetName)
.doWrite(data);
} catch (IOException e) {
log.error("Excel导出失败:", e);
throw new RuntimeException("Excel导出失败:" + e.getMessage());
}
}
/**
* 多sheet Excel导出(直接下载)
* @param response 响应对象
* @param fileName 导出文件名(不带.xlsx)
* @param clazz Excel实体类Class
* @param sheetDataList 每个sheet的名称+数据(Object[0]=sheetName, Object[1]=dataList)
* @param <T> 泛型
*/
public static <T> void exportMultiSheetExcel(HttpServletResponse response, String fileName,
Class<T> clazz, List<Object[]> sheetDataList) {
try {
// 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8)
.replaceAll("\\+", "%20");
response.setHeader("Content-Disposition",
"attachment;filename*=utf-8''" + encodedFileName + ".xlsx");
// 多sheet写入
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), clazz).build();
for (Object[] sheetData : sheetDataList) {
String sheetName = (String) sheetData[0];
List<T> dataList = (List<T>) sheetData[1];
WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
excelWriter.write(dataList, writeSheet);
}
excelWriter.finish();
} catch (IOException e) {
log.error("多sheet Excel导出失败:", e);
throw new RuntimeException("多sheet Excel导出失败:" + e.getMessage());
}
}
/**
* Excel导入(读取上传的文件)
* @param file 上传的Excel文件
* @param clazz Excel实体类Class
* @param listener 数据处理监听器
* @param <T> 泛型
*/
public static <T> void importExcel(MultipartFile file, Class<T> clazz,
com.alibaba.excel.event.AnalysisEventListener<T> listener) {
if (file == null || file.isEmpty()) {
throw new RuntimeException("导入的Excel文件不能为空");
}
try {
// 读取Excel文件
EasyExcel.read(file.getInputStream(), clazz, listener)
.sheet() // 读取第一个sheet
.doRead();
} catch (IOException e) {
log.error("Excel导入失败:", e);
throw new RuntimeException("Excel导入失败:" + e.getMessage());
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# 7. 数据导出功能实现
企业级Excel导出常见场景包括单sheet导出、多sheet导出,以下实现用户信息的导出功能。
# 7.1 业务层接口
在cc.hep.service包下创建UserService.java:
package cc.hep.service;
import cc.hep.entity.UserExcelDTO;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* 用户业务层接口
*/
public interface UserService {
/**
* 获取模拟用户数据(企业级中替换为数据库查询)
*/
List<UserExcelDTO> getUserList();
/**
* 导出用户信息(单sheet)
*/
void exportUserExcel(HttpServletResponse response);
/**
* 导出用户信息(多sheet,按年龄段分组)
*/
void exportMultiSheetUserExcel(HttpServletResponse response);
/**
* 导入用户信息
*/
void importUserExcel(MultipartFile file);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 7.2 业务层实现
在cc.hep.service.impl包下创建UserServiceImpl.java:
package cc.hep.service.impl;
import cc.hep.entity.UserExcelDTO;
import cc.hep.listener.UserExcelListener;
import cc.hep.service.UserService;
import cc.hep.util.EasyExcelUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* 用户业务层实现类
*/
@Slf4j
@Service
public class UserServiceImpl implements UserService {
/**
* 模拟用户数据(企业级中替换为MyBatis/MyBatis-Plus查询)
*/
@Override
public List<UserExcelDTO> getUserList() {
List<UserExcelDTO> userList = new ArrayList<>();
// 模拟5条测试数据
UserExcelDTO user1 = new UserExcelDTO();
user1.setUsername("zhangsan");
user1.setRealName("张三");
user1.setAge(25);
user1.setPhone("13800138000");
user1.setCreateTime(new Date());
UserExcelDTO user2 = new UserExcelDTO();
user2.setUsername("lisi");
user2.setRealName("李四");
user2.setAge(30);
user2.setPhone("13900139000");
user2.setCreateTime(new Date());
UserExcelDTO user3 = new UserExcelDTO();
user3.setUsername("wangwu");
user3.setRealName("王五");
user3.setAge(25);
user3.setPhone("13700137000");
user3.setCreateTime(new Date());
UserExcelDTO user4 = new UserExcelDTO();
user4.setUsername("zhaoliu");
user4.setRealName("赵六");
user4.setAge(30);
user4.setPhone("13600136000");
user4.setCreateTime(new Date());
UserExcelDTO user5 = new UserExcelDTO();
user5.setUsername("sunqi");
user5.setRealName("孙七");
user5.setAge(35);
user5.setPhone("13500135000");
user5.setCreateTime(new Date());
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
userList.add(user5);
return userList;
}
/**
* 单sheet导出
*/
@Override
public void exportUserExcel(HttpServletResponse response) {
List<UserExcelDTO> userList = getUserList();
EasyExcelUtil.exportExcel(response, "用户信息列表", "用户信息", UserExcelDTO.class, userList);
}
/**
* 多sheet导出(按年龄段分组)
*/
@Override
public void exportMultiSheetUserExcel(HttpServletResponse response) {
List<UserExcelDTO> userList = getUserList();
// 按年龄段分组
List<UserExcelDTO> age25List = userList.stream()
.filter(u -> u.getAge() == 25).collect(Collectors.toList());
List<UserExcelDTO> age30List = userList.stream()
.filter(u -> u.getAge() == 30).collect(Collectors.toList());
List<UserExcelDTO> age35List = userList.stream()
.filter(u -> u.getAge() == 35).collect(Collectors.toList());
// 构建多sheet数据
List<Object[]> sheetDataList = new ArrayList<>();
sheetDataList.add(new Object[]{"25岁用户", age25List});
sheetDataList.add(new Object[]{"30岁用户", age30List});
sheetDataList.add(new Object[]{"35岁用户", age35List});
// 调用工具类导出
EasyExcelUtil.exportMultiSheetExcel(response, "分年龄段用户信息",
UserExcelDTO.class, sheetDataList);
}
/**
* 导入用户信息
*/
@Override
public void importUserExcel(MultipartFile file) {
UserExcelListener listener = new UserExcelListener();
EasyExcelUtil.importExcel(file, UserExcelDTO.class, listener);
log.info("Excel导入完成,共处理{}条数据", listener.getUserList().size());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# 7.3 控制器实现
在cc.hep.controller包下创建UserController.java:
package cc.hep.controller;
import cc.hep.common.Result;
import cc.hep.service.UserService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
* 用户控制器
* 提供Excel导入导出接口
*/
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor // 构造器注入(企业级推荐)
public class UserController {
private final UserService userService;
/**
* 导出用户信息(单sheet)
*/
@GetMapping("/export")
public void exportUserExcel(HttpServletResponse response) {
userService.exportUserExcel(response);
}
/**
* 导出用户信息(多sheet)
*/
@GetMapping("/export/multi-sheet")
public void exportMultiSheetUserExcel(HttpServletResponse response) {
userService.exportMultiSheetUserExcel(response);
}
/**
* 导入用户信息
*/
@PostMapping("/import")
public Result<?> importUserExcel(@RequestParam("file") MultipartFile file) {
userService.importUserExcel(file);
return Result.success("Excel导入成功");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 8. 数据导入功能实现
企业级Excel导入需处理数据读取、校验、批量入库,以下实现用户信息导入功能。
# 8.1 导入监听器
在cc.hep.listener包下创建UserExcelListener.java(处理导入数据):
package cc.hep.listener;
import cc.hep.entity.UserExcelDTO;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
/**
* 用户Excel导入监听器
* 处理数据读取、校验、批量处理
*/
@Slf4j
public class UserExcelListener extends AnalysisEventListener<UserExcelDTO> {
/**
* 批量处理阈值(企业级可配置)
*/
private static final int BATCH_SIZE = 100;
/**
* 临时存储读取的数据
*/
private List<UserExcelDTO> userList = new ArrayList<>(BATCH_SIZE);
/**
* 每读取一行数据触发
*/
@Override
public void invoke(UserExcelDTO userExcelDTO, AnalysisContext analysisContext) {
log.info("读取到Excel数据:{}", userExcelDTO);
// 数据校验(企业级可扩展更多规则)
validateData(userExcelDTO);
userList.add(userExcelDTO);
// 达到阈值则批量处理(企业级中替换为批量入库)
if (userList.size() >= BATCH_SIZE) {
handleBatchData();
userList.clear();
}
}
/**
* 所有数据读取完成后触发
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
// 处理剩余数据
handleBatchData();
log.info("Excel数据读取完成,共处理{}条数据", userList.size());
}
/**
* 数据校验
*/
private void validateData(UserExcelDTO userExcelDTO) {
// 用户名非空校验
if (userExcelDTO.getUsername() == null || userExcelDTO.getUsername().trim().isEmpty()) {
throw new RuntimeException("用户名不能为空");
}
// 手机号格式校验
if (userExcelDTO.getPhone() != null && !userExcelDTO.getPhone().matches("^1[3-9]\\d{9}$")) {
throw new RuntimeException("手机号格式错误:" + userExcelDTO.getPhone());
}
// 年龄范围校验
if (userExcelDTO.getAge() != null && (userExcelDTO.getAge() < 0 || userExcelDTO.getAge() > 150)) {
throw new RuntimeException("年龄超出合理范围:" + userExcelDTO.getAge());
}
}
/**
* 批量处理数据(企业级中替换为数据库批量插入)
*/
private void handleBatchData() {
log.info("批量处理{}条用户数据", userList.size());
// 示例:调用Service批量入库
// userService.batchSave(userList);
}
/**
* 获取读取的所有数据(供外部调用)
*/
public List<UserExcelDTO> getUserList() {
return userList;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# 9. 接口测试
完成代码开发后,启动项目(运行SpringBootEasyExcelApplication.java),测试导入导出接口。
# 9.1 导出接口测试
- 单sheet导出:访问
http://localhost:8080/user/export,浏览器自动下载「用户信息列表.xlsx」 - 多sheet导出:访问
http://localhost:8080/user/export/multi-sheet,自动下载「分年龄段用户信息.xlsx」
# 9.2 导入接口测试
- 创建POST请求,地址:
http://localhost:8080/user/import - 请求体选择「form-data」,Key为「file」,类型选「File」,选择本地符合格式的Excel文件
- 发送请求,成功返回:
{"code":200,"msg":"操作成功","data":"Excel导入成功"}
# 10. 企业级优化与注意事项
# 10.1 性能优化
- 批量处理:导入时设置合理的批量阈值(如100/500),减少数据库交互次数
- 内存控制:EasyExcel逐行读取避免OOM,但需控制监听器中临时数据量
- 异步处理:大文件导入使用
@Async异步处理,避免接口超时 - 数据库优化:批量插入使用MyBatis-Plus的
saveBatch方法
# 10.2 关键注意事项
- 版本兼容:EasyExcel 3.3.2适配JDK17和SpringBoot3,避免版本冲突
- 数据校验:导入必须添加完善的校验规则,防止脏数据入库
- 文件名编码:导出时使用
URLEncoder处理中文文件名,避免乱码 - 异常友好:全局异常处理器返回用户可理解的提示信息
- 权限控制:企业级中需为导入导出接口添加权限校验
# 10.3 扩展功能
- 模板导出:基于Excel模板填充数据(如合同、报表模板)
- 自定义样式:设置字体、颜色、边框、合并单元格
- 导入结果反馈:生成错误日志Excel,返回错误行和原因
- 导出进度:大文件导出时返回进度条(WebSocket/异步通知)
# 总结
- 企业级SpringBoot集成EasyExcel的核心流程:环境准备→项目初始化→依赖引入→基础架构搭建→实体设计→工具类封装→业务/控制器实现→接口测试。
- 通用工具类是企业级开发的核心,封装单/多sheet导出、导入方法可大幅提升代码复用性。
- 企业级优化重点关注批量处理、数据校验、异常处理和版本兼容,确保Excel处理的性能和稳定性。