SpringBoot集成EasyExcel實(shí)現(xiàn)Excel導(dǎo)入的方法
第一次正式的寫文章進(jìn)行分享,如果文章中有什么問題,歡迎大家在文末的群內(nèi)反饋。
一、背景
為什么會(huì)用Easyexcel來做Excel上傳
平時(shí)項(xiàng)目中經(jīng)常使用EasyExcel從本地讀取Excel中的數(shù)據(jù),還有一個(gè)前端頁面對需要處理的數(shù)據(jù)進(jìn)行一些配置(如:Excel所在的文件夾,Excel的文件名,以及Sheet列名、處理數(shù)據(jù)需要的某些參數(shù)),由于每次都是讀取的本地的文件,我就在想,如果某一天需要通過前端上傳excel給我,讓我來進(jìn)行處理我又應(yīng)該怎么辦呢?我怎么才能在盡量少修改代碼的前提下實(shí)現(xiàn)這個(gè)功能呢(由于公司經(jīng)常改需求,項(xiàng)目已經(jīng)重新寫了3次了)?后來查了很多資料,發(fā)現(xiàn)Excel可以使用InPutStream流來讀取Excel,我就突然明白了什么。
阿里巴巴語雀團(tuán)隊(duì)對EasyExcel是這樣介紹的
Java解析、生成Excel比較有名的框架有Apache poi、jxl。但他們都存在一個(gè)嚴(yán)重的問題就是非常的耗內(nèi)存,
poi有一套SAX模式的API可以一定程度的解決一些內(nèi)存溢出的問題,但POI還是有一些缺陷,比如07版Excel解壓
縮以及解壓后存儲(chǔ)都是在內(nèi)存中完成的,內(nèi)存消耗依然很大。easyexcel重寫了poi對07版Excel的解析,能夠原
本一個(gè)3M的excel用POI sax依然需要100M左右內(nèi)存降低到幾M,并且再大的excel不會(huì)出現(xiàn)內(nèi)存溢出,03版依賴
POI的sax模式。在上層做了模型轉(zhuǎn)換的封裝,讓使用者更加簡單方便。
當(dāng)然還有急速模式能更快,但是內(nèi)存占用會(huì)在100M多一點(diǎn)。
二、集成EasyExcel?
薩達(dá)
1、 在pom.xml中添加EasyExcel依賴
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.3</version> </dependency>
2、創(chuàng)建EasyExcel映射實(shí)體類
import com.alibaba.excel.annotation.ExcelProperty; public class ExcelEntity { // ExcelProperty中的參數(shù)要對應(yīng)Excel中的標(biāo)題 @ExcelProperty("ID") private int ID; @ExcelProperty("NAME") private String name; @ExcelProperty("AGE") private int age; public ExcelEntity() { } public ExcelEntity(int ID, String name, int age) { this.ID = ID; this.name = name; this.age = age; } public int getID() { return ID; } public void setID(int ID) { this.ID = ID; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
3、創(chuàng)建自定義Easyexcel的監(jiān)聽類
- 這個(gè)監(jiān)聽類里面每一個(gè)ExcelEntity對象代表一行數(shù)據(jù)
- 在這個(gè)監(jiān)聽類里面可以對讀取到的每一行數(shù)據(jù)進(jìn)行單獨(dú)操作
- 這里的讀取的數(shù)據(jù)是按照Excel中每一條數(shù)據(jù)的順序進(jìn)行讀取的
import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import java.util.ArrayList; import java.util.List; public class UploadExcelListener extends AnalysisEventListener<ExcelEntity> { private static final Logger logger = LoggerFactory.getLogger(LoggerItemController.class); public static final List<ExcelEntity> list = new ArrayList<>(); @Override public void invoke(ExcelEntity excelEntity, AnalysisContext context) { logger.info(String.valueOf(excelEntity.getID())); logger.info(excelEntity.getName()); logger.info(String.valueOf(excelEntity.getAge())); list.add(excelEntity); }
4、創(chuàng)建controller
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; import java.util.List; @RestController @CrossOrigin @RequestMapping("/loggerItem") public class LoggerItemController { // MultipartFile 這個(gè)類一般是用來接受前臺(tái)傳過來的文件 @PostMapping("/upload") public List<ExcelEntity> upload(@RequestParam(value = "multipartFile") MultipartFile multipartFile){ if (multipartFile == null){ return null; } InputStream in = null; try { // 從multipartFile獲取InputStream流 in = multipartFile.getInputStream(); /* * EasyExcel 有多個(gè)不同的read方法,適用于多種需求 * 這里調(diào)用EasyExcel中通過InputStream流方式讀取Excel的Read方法 * 他會(huì)返回一個(gè)ExcelReaderBuilder類型的返回值 * ExcelReaderBuilder中有一個(gè)doReadAll方法,會(huì)讀取所有的Sheet */ EasyExcel.read(in,ExcelEntity.class,new UploadExcelListener()) .sheet("Sheet1") .doRead(); // 每次EasyExcel的read方法讀取完之后都會(huì)關(guān)閉流,我這里為了試驗(yàn)doReadAll方法,所以重新獲取了一次 in = multipartFile.getInputStream(); /* * ExcelReaderBuilder中的Sheet方法,需要添加讀取的Sheet名作為參數(shù) * 并且不要忘記在后面再調(diào)用一下doReadAll方法,否則不會(huì)進(jìn)行讀取操作 */ EasyExcel.read(in,ExcelEntity.class,new UploadExcelListener()).doReadAll(); } catch (IOException e) { e.printStackTrace(); } return UploadExcelListener.list; } }
5、application.yml配置
server: # 指定端口號 port: 8080 spring: servlet: multipart: # 配置單個(gè)上傳文件大小 file-size-threshold: 100M # 配置總上傳大小 max-request-size: 300M
6、測試
我們先搞一個(gè)簡單的Excel,用來測試
然后通過Postman模擬發(fā)送請求
- 選擇Post請求并輸入請求地址
- 在下面選擇Body
- Key的框中輸入controller中的請求的方法中的參數(shù),后面的下拉框中選擇File
- VALUE框中有一個(gè)Select File ,點(diǎn)擊后選擇自己剛才創(chuàng)建的測試的Excel
- 最后點(diǎn)擊Send發(fā)送請求
返回值如下:
由于我讀了兩次都放在同一個(gè)List中返回,所以返回值中有8個(gè)對象。
[ { "name": "小黑", "age": 25, "id": 1 }, { "name": "小白", "age": 22, "id": 2 }, { "name": "小黃", "age": 22, "id": 3 }, { "name": "小綠", "age": 23, "id": 4 }, { "name": "小黑", "age": 25, "id": 1 }, { "name": "小白", "age": 22, "id": 2 }, { "name": "小黃", "age": 22, "id": 3 }, { "name": "小綠", "age": 23, "id": 4 } ]
三、EasyExcel中的Read方法匯總
/** * Build excel the read * * @return Excel reader builder. */ public static ExcelReaderBuilder read() { return new ExcelReaderBuilder(); } /** * Build excel the read * * @param file * File to read. * @return Excel reader builder. */ public static ExcelReaderBuilder read(File file) { return read(file, null, null); } /** * Build excel the read * * @param file * File to read. * @param readListener * Read listener. * @return Excel reader builder. */ public static ExcelReaderBuilder read(File file, ReadListener readListener) { return read(file, null, readListener); } /** * Build excel the read * * @param file * File to read. * @param head * Annotate the class for configuration information. * @param readListener * Read listener. * @return Excel reader builder. */ public static ExcelReaderBuilder read(File file, Class head, ReadListener readListener) { ExcelReaderBuilder excelReaderBuilder = new ExcelReaderBuilder(); excelReaderBuilder.file(file); if (head != null) { excelReaderBuilder.head(head); } if (readListener != null) { excelReaderBuilder.registerReadListener(readListener); } return excelReaderBuilder; } /** * Build excel the read * * @param pathName * File path to read. * @return Excel reader builder. */ public static ExcelReaderBuilder read(String pathName) { return read(pathName, null, null); } /** * Build excel the read * * @param pathName * File path to read. * @param readListener * Read listener. * @return Excel reader builder. */ public static ExcelReaderBuilder read(String pathName, ReadListener readListener) { return read(pathName, null, readListener); } /** * Build excel the read * * @param pathName * File path to read. * @param head * Annotate the class for configuration information. * @param readListener * Read listener. * @return Excel reader builder. */ public static ExcelReaderBuilder read(String pathName, Class head, ReadListener readListener) { ExcelReaderBuilder excelReaderBuilder = new ExcelReaderBuilder(); excelReaderBuilder.file(pathName); if (head != null) { excelReaderBuilder.head(head); } if (readListener != null) { excelReaderBuilder.registerReadListener(readListener); } return excelReaderBuilder; } /** * Build excel the read * * @param inputStream * Input stream to read. * @return Excel reader builder. */ public static ExcelReaderBuilder read(InputStream inputStream) { return read(inputStream, null, null); } /** * Build excel the read * * @param inputStream * Input stream to read. * @param readListener * Read listener. * @return Excel reader builder. */ public static ExcelReaderBuilder read(InputStream inputStream, ReadListener readListener) { return read(inputStream, null, readListener); } /** * Build excel the read * * @param inputStream * Input stream to read. * @param head * Annotate the class for configuration information. * @param readListener * Read listener. * @return Excel reader builder. */ public static ExcelReaderBuilder read(InputStream inputStream, Class head, ReadListener readListener) { ExcelReaderBuilder excelReaderBuilder = new ExcelReaderBuilder(); excelReaderBuilder.file(inputStream); if (head != null) { excelReaderBuilder.head(head); } if (readListener != null) { excelReaderBuilder.registerReadListener(readListener); } return excelReaderBuilder; }
所有的方法都在這兒了,其實(shí)如果看不懂到底應(yīng)該調(diào)用哪一個(gè)read方法的話,可以以根據(jù)自己所能得到的參數(shù)來判斷。
四、擴(kuò)展
讀取本地Excel
public static void main(String[] args) { EasyExcel.read("C:/Users/Lonely Programmer/Desktop/新建 Microsoft Excel 工作表.xlsx" ,ExcelEntity.class ,new UploadExcelListener()) .doReadAll(); }
讀取本地的Excel和通過InPutStream流讀取的方式是一樣的,只是參數(shù)變了,原本傳的是InPutStream流,現(xiàn)在傳的是文件的絕對路徑。我這里監(jiān)聽類和映射實(shí)體類都沒有變,和上傳用的是同一個(gè),大家也可以根據(jù)需求來設(shè)定自己的監(jiān)聽類與實(shí)體類
MultipartFile文檔地址:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/multipart/MultipartFile.html
翻譯是通過Google Chrome自帶翻譯插件進(jìn)行翻譯的,建議大家使用Google Chrome打開,自帶翻譯功能
到此這篇關(guān)于SpringBoot集成EasyExcel實(shí)現(xiàn)Excel導(dǎo)入的方法的文章就介紹到這了,更多相關(guān)SpringBoot實(shí)現(xiàn)Excel導(dǎo)入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot中EasyExcel實(shí)現(xiàn)Excel文件的導(dǎo)入導(dǎo)出
- SpringBoot整合EasyExcel實(shí)現(xiàn)文件導(dǎo)入導(dǎo)出
- java使用EasyExcel導(dǎo)入導(dǎo)出excel
- Java+EasyExcel實(shí)現(xiàn)文件的導(dǎo)入導(dǎo)出
- EasyExcel實(shí)現(xiàn)導(dǎo)入+各種數(shù)據(jù)校驗(yàn)功能
- Java使用EasyExcel實(shí)現(xiàn)Excel的導(dǎo)入導(dǎo)出
- Java使用easyExcel批量導(dǎo)入數(shù)據(jù)詳解
- Java EasyExcel導(dǎo)入帶圖片的完整過程記錄
相關(guān)文章
SpringBoot入坑筆記之spring-boot-starter-web 配置文件的使用
本篇向小伙伴介紹springboot配置文件的配置,已經(jīng)全局配置參數(shù)如何使用的。需要的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-01-01Java實(shí)現(xiàn)的文本字符串操作工具類實(shí)例【數(shù)據(jù)替換,加密解密操作】
這篇文章主要介紹了Java實(shí)現(xiàn)的文本字符串操作工具類,可實(shí)現(xiàn)數(shù)據(jù)替換、加密解密等操作,涉及java字符串遍歷、編碼轉(zhuǎn)換、替換等相關(guān)操作技巧,需要的朋友可以參考下2017-10-10Java 使用 HttpClient 發(fā)送 GET請求和 POST請求
本文主要介紹了Java 使用 HttpClient 發(fā)送 GET請求和 POST請求,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08Mybatis Plus整合PageHelper分頁的實(shí)現(xiàn)示例
這篇文章主要介紹了Mybatis Plus整合PageHelper分頁的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09關(guān)于ReentrantLock的實(shí)現(xiàn)原理解讀
這篇文章主要介紹了關(guān)于ReentrantLock的實(shí)現(xiàn)原理,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06java swing中實(shí)現(xiàn)拖拽功能示例
這篇文章主要介紹了java swing中實(shí)現(xiàn)拖拽功能示例,需要的朋友可以參考下2014-04-04java 使用JDBC構(gòu)建簡單的數(shù)據(jù)訪問層實(shí)例詳解
以下是如何使用JDBC構(gòu)建一個(gè)數(shù)據(jù)訪問層,包括數(shù)據(jù)轉(zhuǎn)換(將從數(shù)據(jù)庫中查詢的數(shù)據(jù)封裝到對應(yīng)的對象中……),數(shù)據(jù)庫的建立,以及如何連接到數(shù)據(jù)庫,需要的朋友可以參考下2016-11-11詳解JVM的內(nèi)存對象介紹[創(chuàng)建和訪問]
這篇文章主要介紹了JVM的內(nèi)存對象介紹[創(chuàng)建和訪問],文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03