SpringBoot整合FastExcel實現(xiàn)導(dǎo)入導(dǎo)出功能的操作詳解
一、前言
在微服務(wù)項目中經(jīng)常會涉及到excel的導(dǎo)入導(dǎo)出功能,隨著要處理的業(yè)務(wù)數(shù)據(jù)量越來越大,這也對程序提出了更高的要求,因為大批量的數(shù)據(jù)導(dǎo)入導(dǎo)出對性能提出了更高的挑戰(zhàn)。在早些年使用poi等工具進行導(dǎo)入導(dǎo)出的時候,經(jīng)常會被吐槽有各種問題,比如API使用復(fù)雜,數(shù)據(jù)量過大時容易OOM等問題,所以在后面當(dāng)EasyExcel推出來之后,其優(yōu)異的性能得到了很多程序開發(fā)者的認可。可惜的是,隨著EasyExcel的設(shè)計者離場,EasyExcel的維護面臨著考驗,于是又推出FastExcel 。作為EasyExcel的替代者,不僅完全兼容EasyExcel的功能,同時也對其進行了進一步的優(yōu)化,并增加了一些新的功能,本篇將詳細介紹下FastExcel 的使用。
二、FastExcel 介紹
2.1 FastExcel 是什么
FastExcel 是一款基于 Java 的開源庫,旨在提供快速、簡潔且能解決大文件內(nèi)存溢出問題的 Excel 處理工具。它兼容 EasyExcel,提供性能優(yōu)化、bug 修復(fù),并新增了如讀取指定行數(shù)和將 Excel 轉(zhuǎn)換為 PDF 的功能。
FastExcel 以 MIT 協(xié)議發(fā)布,適用于任何商業(yè)場景。其高性能讀寫、簡單易用的 API 和流式操作能力,使其特別適合處理大規(guī)模數(shù)據(jù)。FastExcel 支持無縫從 EasyExcel 遷移,極大地簡化了 Excel 文件的讀寫操作,提升了開發(fā)效率。git地址:GitHub - apache/fesod: Fast. Easy. Done. Processing Excels without worrying about large files causing OOM.

2.2 FastExcel 主要特點
FastExcel 具備如下特點:
完全兼容EasyExcel的所有功能和特性,這使得用戶可以無縫遷移和過渡;
從EasyExcel升級到EasyExcel,只需要簡單的更換包名和maven依賴即可完成成升級;
從功能上,比EasyExcel提供更多創(chuàng)新改進,比如 FastExcel 1.0.0版本新增了:
- 讀取excel指定的行數(shù);
- 將excel轉(zhuǎn)為pdf;
2.3 FastExcel 主要功能
FastExcel 主要提供了以下功能
- 高性能讀寫:FastExcel 專注于性能優(yōu)化,能高效處理大規(guī)模 Excel 數(shù)據(jù),顯著降低內(nèi)存占用。
- 簡單易用:提供簡潔直觀的 API,易于集成和使用。
- 流式操作:支持流式讀取,減少一次性加載大量數(shù)據(jù)的問題。
- 讀取指定行數(shù):可以根據(jù)需求,只讀取感興趣的部分數(shù)據(jù),提高數(shù)據(jù)處理效率。
- Excel 轉(zhuǎn)換為 PDF:支持直接將 Excel 文件轉(zhuǎn)換為 PDF,滿足多樣化的文檔輸出需求。
2.4 FastExcel 核心技術(shù)實現(xiàn)原理
FastExcel 核心原理參考下面的理解:
- 內(nèi)存優(yōu)化:基于流式讀取技術(shù),不需要一次性將整個 Excel 文件加載到內(nèi)存中,逐行或逐塊讀取數(shù)據(jù)。
- 事件驅(qū)動模型:基于實現(xiàn)
ReadListener接口處理讀取操作。當(dāng)讀取到數(shù)據(jù)時,會觸發(fā)接口中的方法,如invoke方法,支持開發(fā)者對每行數(shù)據(jù)進行即時處理。 - 注解映射:用注解將 Excel 文件中的列與 Java 對象的屬性進行映射。開發(fā)者能輕松地將 Excel 數(shù)據(jù)轉(zhuǎn)換為 Java 對象,同時也支持反向操作,將 Java 對象寫入 Excel。
三、springboot 整合FastExcel 操作過程
接下來通過實際案例演示下如何在springboot 項目中整合FastExcel 。
3.1 開發(fā)環(huán)境準(zhǔn)備
為了確保后續(xù)你的工程也能正常的使用,建議參考下面的技術(shù)棧:
- JDK 17;
- SpringBoot 3.3 ;
3.2 完整整合過程
3.2.1 添加依賴
創(chuàng)建一個全新的springboot工程,在pom文件中添加如下的依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.idev.excel</groupId>
<artifactId>fastexcel</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>3.2.2 配置文件信息
本例僅演示導(dǎo)入導(dǎo)出功能,配置文件只需要配置下端口即可
server: port: 8082
3.2.3 增加一個實體類
之前有使用過easyexcel經(jīng)驗的同學(xué)應(yīng)該不陌生,一般導(dǎo)入的數(shù)據(jù)最終需要落庫,為了讓excel的列與數(shù)據(jù)庫表字段進行對應(yīng),一般需要一個自定義的對象,用easyexcel提供的相應(yīng)注解來標(biāo)準(zhǔn)字段信息,這樣easyexcel在解析的時候才能進行映射,如下,增加一個自定義的User類,里面有3個基本屬性
package com.congge.entity;
import cn.idev.excel.annotation.ExcelProperty;
import lombok.*;
@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {
@ExcelProperty("編號")
private Integer id;
@ExcelProperty("名字")
private String name;
@ExcelProperty("年齡")
private Integer age;
}3.2.4 增加一個事件監(jiān)聽器
監(jiān)聽器的作用也可以理解為FastExcel 內(nèi)部封裝的一個兼具數(shù)據(jù)讀取,數(shù)據(jù)緩存,數(shù)據(jù)轉(zhuǎn)換為一體的組件,有了這個監(jiān)聽器,上層只需要在上傳或下載excel的時候代入進去,該監(jiān)聽器就可以發(fā)揮作用,從而完成數(shù)據(jù)的轉(zhuǎn)換。參考下面的代碼。
package com.congge.component;
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;
public class BaseExcelListener<T> extends AnalysisEventListener<T> {
private final List<T> dataList = new ArrayList<>();
@Override
public void invoke(T t, AnalysisContext analysisContext) {
// 每讀取一行數(shù)據(jù),就將其添加到dataList中
dataList.add(t);
System.out.println("解析到數(shù)據(jù): " + t);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
System.out.println("讀取完成,共讀取了 " + dataList.size() + " 條數(shù)據(jù)");
}
public List<T> getDataList() {
return dataList;
}
}3.2.5 增加一個測試使用的接口類
為了方便測試看效果,增加一個controller控制器類,提供2個基本的上傳下載接口,參考下面的代碼
package com.congge.controller;
import cn.idev.excel.FastExcel;
import com.congge.component.BaseExcelListener;
import com.congge.entity.User;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
@RestController
@RequestMapping("/api/excel")
public class ExcelController {
/**
* Excel導(dǎo)出功能
* @param response
* @throws IOException
* localhost:8082/api/excel/download
*/
@GetMapping("/download")
public void download(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("用戶數(shù)據(jù)", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
// 寫入數(shù)據(jù)
FastExcel.write(response.getOutputStream(), User.class)
.sheet("用戶信息")
.doWrite(buildData());
}
/**
* Excel導(dǎo)出功能
* @param file
* @return
* localhost:8082/api/excel/upload
*/
@PostMapping("/upload")
public ResponseEntity<String> upload(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return ResponseEntity.badRequest().body("請選擇一個文件上傳!");
}
try {
BaseExcelListener<User> baseExcelListener = new BaseExcelListener<>();
FastExcel.read(file.getInputStream(), User.class, baseExcelListener)
.sheet()
.doRead();
// 獲取讀取的數(shù)據(jù)
List<User> dataList = baseExcelListener.getDataList();
System.out.println("讀取到的數(shù)據(jù): " + dataList);
return ResponseEntity.ok("文件上傳并處理成功!共處理 " + dataList.size() + " 條數(shù)據(jù)");
} catch (IOException e) {
return ResponseEntity.status(500).body("文件處理失敗: " + e.getMessage());
}
}
// 創(chuàng)建測試數(shù)據(jù)
private List<User> buildData() {
User user1 = new User();
user1.setId(1);
user1.setName("張三");
user1.setAge(18);
User user2 = new User();
user2.setId(2);
user2.setName("李四");
user2.setAge(19);
return List.of(user1, user2);
}
}3.2.6 效果測試與驗證
分別測試一下上面兩個接口,啟動工程
1)下載接口測試
啟動工程后,瀏覽器調(diào)用接口:localhost:8082/api/excel/download ,按照預(yù)期的效果下載為一個excel

2)上傳接口測試
使用接口工具模擬接口調(diào)用,就用上面的這個excel,主要是看看控制臺的輸出日志,接口調(diào)用成功

通過控制臺的輸出日志可以看到,待導(dǎo)入的數(shù)據(jù)也成功進行了加載

3.2.7 補充說明
有的同學(xué)可能會有這樣的擔(dān)心,當(dāng)excel數(shù)據(jù)量太大的時候,會不會有性能問題,關(guān)于這一點,F(xiàn)astExcel 的作者在設(shè)計的時候就考慮到了,當(dāng)你要上傳的excel里面的數(shù)據(jù)量比較大,工具方法內(nèi)部會進行分批讀取,從而減少OOM的風(fēng)險

3.3 FastExcel 高級功能
3.3.1 大量數(shù)據(jù)導(dǎo)入優(yōu)化
對于大數(shù)據(jù)量導(dǎo)入,建議使用批量處理模式,因此需要改寫和優(yōu)化上述的事件監(jiān)聽器,參考下面的代碼
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;
public class BatchExcelListener<T> extends AnalysisEventListener<T> {
private static final int BATCH_COUNT = 1000;
private List<T> dataList = new ArrayList<>(BATCH_COUNT);
@Override
public void invoke(T data, AnalysisContext context) {
dataList.add(data);
// 達到BATCH_COUNT了,需要去存儲一次數(shù)據(jù)庫,防止數(shù)據(jù)幾萬條數(shù)據(jù)在內(nèi)存,容易OOM
if (dataList.size() >= BATCH_COUNT) {
saveData();
// 存儲完成清理 list
dataList = new ArrayList<>(BATCH_COUNT);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 確保最后遺留的數(shù)據(jù)也存儲到數(shù)據(jù)庫
if (!dataList.isEmpty()) {
saveData();
}
System.out.println("所有數(shù)據(jù)解析完成!");
}
private void saveData() {
// 這里實現(xiàn)批量保存到數(shù)據(jù)庫的邏輯
System.out.println("批量保存" + dataList.size() + "條數(shù)據(jù)到數(shù)據(jù)庫");
// userService.saveBatch(dataList);
}
}3.3.2 excel轉(zhuǎn)pdf功能
添加下面的測試接口驗證excel轉(zhuǎn)pdf功能
//localhost:8082/api/excel/convertToPdf
@GetMapping("/convertToPdf")
public void convertToPdf(){
String excelPath = "D:\\data\\用戶數(shù)據(jù).xlsx";
String pdfFilePath = "D:\\data\\用戶數(shù)據(jù).pdf";
FastExcel.convertToPdf(new File(excelPath), new File(pdfFilePath), null, null);
System.out.println("轉(zhuǎn)換完成");
}3.4 EasyExcel 升級到FastExcel
有一些伙伴之前項目中使用的是EasyExcel ,那么如果要升級到FastExcel該怎么做呢,可以參考下面的步驟
3.4.1 修改依賴
將 EasyExcel 的依賴替換為 FastExcel 的依賴,如下:
<!-- easyexcel 依賴 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>xxxx</version> </dependency>
依賴替換為:
<dependency> <groupId>cn.idev.excel</groupId> <artifactId>fastexcel</artifactId> <version>1.0.0</version> </dependency>
3.4.2 修改代碼
將 EasyExcel 的包名替換為 FastExcel 的包名,如下:
// 將 easyexcel 的包名替換為 FastExcel 的包名 import com.alibaba.excel.**;
替換為:
import cn.idev.excel.**;
本文通過案例代碼演示了FastExcel 的使用,通過案例介紹了FastExcel 具體的導(dǎo)入導(dǎo)出的使用,更多功能有興趣的同學(xué)可以繼續(xù)深入研究,本篇到此結(jié)束,感謝觀看。
到此這篇關(guān)于SpringBoot整合FastExcel實現(xiàn)導(dǎo)入導(dǎo)出功能的操作詳解的文章就介紹到這了,更多相關(guān)SpringBoot FastExcel導(dǎo)入導(dǎo)出內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 一文帶你了解FastExcel的使用
- Java使用FastExcel實現(xiàn)合并單元格
- Java使用FastExcel導(dǎo)入支持多種時間格式
- 在Vue+SpringBoot應(yīng)用中實現(xiàn)導(dǎo)入導(dǎo)出excel表功能全過程
- SpringBoot集成EasyExcel實現(xiàn)百萬級別的數(shù)據(jù)導(dǎo)入導(dǎo)出實踐指南
- SpringBoot+EasyExcel實現(xiàn)自定義復(fù)雜樣式導(dǎo)入導(dǎo)出
- Springboot整合easyexcel實現(xiàn)一個接口任意表的Excel導(dǎo)入導(dǎo)出
- SpringBoot使用Apache?POI實現(xiàn)導(dǎo)入導(dǎo)出Excel文件
相關(guān)文章
MyBatis-Flex+ShardingSphere-JDBC多數(shù)據(jù)源分庫分表實現(xiàn)
本文介紹了使用MyBatis-Flex和ShardingSphere-JDBC實現(xiàn)多數(shù)據(jù)源分庫分表的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-10-10
Windows環(huán)境IDEA下Ranger1.2.0源碼編譯詳細流程
本文給大家講解Windows環(huán)境IDEA下Ranger1.2.0源碼編譯過程,通過配置Tomcat,發(fā)布?security-admin-web項目,編譯啟動tomcat即可完成,需要的朋友參考下2021-06-06
springboot+mybatis-plus基于攔截器實現(xiàn)分表的示例代碼
本文主要介紹了springboot+mybatis-plus基于攔截器實現(xiàn)分表,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11
Mybatis原始執(zhí)行方式Executor代碼實例
這篇文章主要介紹了Mybatis原始執(zhí)行方式Executor代碼實例解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07
Java中的異步操作CompletableFuture示例詳解
CompletableFuture是Java8引入的異步編程工具,支持非阻塞的鏈?zhǔn)秸{(diào)用和組合操作,提供了強大的異步任務(wù)編排能力,本文通過實例代碼講解Java中的異步操作CompletableFuture,感興趣的朋友跟隨小編一起看看吧2026-02-02
swagger添加權(quán)限驗證保證API(接口)安全性(兩種方法)
這篇文章主要介紹了swagger添加權(quán)限驗證保證API(接口)安全性(兩種方法),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01
使用Java 8 Lambda表達式將實體映射到DTO的操作
這篇文章主要介紹了使用Java 8 Lambda表達式將實體映射到DTO的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
使用IDEA搭建一個簡單的SpringBoot項目超詳細過程
這篇文章主要介紹了使用IDEA搭建一個簡單的SpringBoot項目超詳細過程,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02

