# 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项目

001

# 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
1
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>
1
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;
    }
}
1
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("服务器内部错误,请联系管理员");
    }
}
1
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  # 项目端口
1
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; // 创建时间
}
1
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;
}
1
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());
        }
    }
}
1
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);
}
1
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());
    }
}
1
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导入成功");
    }
}
1
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;
    }
}
1
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 导入接口测试

  1. 创建POST请求,地址:http://localhost:8080/user/import
  2. 请求体选择「form-data」,Key为「file」,类型选「File」,选择本地符合格式的Excel文件
  3. 发送请求,成功返回:{"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/异步通知)

# 总结

  1. 企业级SpringBoot集成EasyExcel的核心流程:环境准备→项目初始化→依赖引入→基础架构搭建→实体设计→工具类封装→业务/控制器实现→接口测试。
  2. 通用工具类是企业级开发的核心,封装单/多sheet导出、导入方法可大幅提升代码复用性。
  3. 企业级优化重点关注批量处理、数据校验、异常处理和版本兼容,确保Excel处理的性能和稳定性。
最近更新: 2026/2/3
 |  Copyright © -Present Kelsen All Rights Reserved. | Author KelsenJing