1. 程式人生 > 程式設計 >SpringBoot整合EasyExcel實現Excel匯入的方法

SpringBoot整合EasyExcel實現Excel匯入的方法

第一次正式的寫文章進行分享,如果文章中有什麼問題,歡迎大家在文末的群內反饋。

一、背景

為什麼會用Easyexcel來做Excel上傳

平時專案中經常使用EasyExcel從本地讀取Excel中的資料,還有一個前端頁面對需要處理的資料進行一些配置(如:Excel所在的資料夾,Excel的檔名,以及Sheet列名、處理資料需要的某些引數),由於每次都是讀取的本地的檔案,我就在想,如果某一天需要通過前端上傳excel給我,讓我來進行處理我又應該怎麼辦呢?我怎麼才能在儘量少修改程式碼的前提下實現這個功能呢(由於公司經常改需求,專案已經重新寫了3次了)?後來查了很多資料,發現Excel可以使用InPutStream流來讀取Excel,我就突然明白了什麼。

阿里巴巴語雀團隊對EasyExcel是這樣介紹的

Java解析、生成Excel比較有名的框架有Apache poi、jxl。但他們都存在一個嚴重的問題就是非常的耗記憶體,
poi有一套SAX模式的API可以一定程度的解決一些記憶體溢位的問題,但POI還是有一些缺陷,比如07版Excel解壓
縮以及解壓後儲存都是在記憶體中完成的,記憶體消耗依然很大。easyexcel重寫了poi對07版Excel的解析,能夠原
本一個3M的excel用POI sax依然需要100M左右記憶體降低到幾M,並且再大的excel不會出現記憶體溢位,03版依賴
POI的sax模式。在上層做了模型轉換的封裝,讓使用者更加簡單方便。

當然還有急速模式能更快,但是記憶體佔用會在100M多一點。

二、整合EasyExcel?

薩達

1、 在pom.xml中新增EasyExcel依賴

 <dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>easyexcel</artifactId>
   <version>2.1.3</version>
  </dependency>

2、建立EasyExcel對映實體類

import com.alibaba.excel.annotation.ExcelProperty;

public class ExcelEntity {
 // ExcelProperty中的引數要對應Excel中的標題
 @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、建立自定義Easyexcel的監聽類

  • 這個監聽類裡面每一個ExcelEntity物件代表一行資料
  • 在這個監聽類裡面可以對讀取到的每一行資料進行單獨操作
  • 這裡的讀取的資料是按照Excel中每一條資料的順序進行讀取的
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、建立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 這個類一般是用來接受前臺傳過來的檔案
 @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 有多個不同的read方法,適用於多種需求
    * 這裡呼叫EasyExcel中通過InputStream流方式讀取Excel的Read方法
    * 他會返回一個ExcelReaderBuilder型別的返回值
    * ExcelReaderBuilder中有一個doReadAll方法,會讀取所有的Sheet
    */
   EasyExcel.read(in,ExcelEntity.class,new UploadExcelListener())
     .sheet("Sheet1")
     .doRead();

   // 每次EasyExcel的read方法讀取完之後都會關閉流,我這裡為了試驗doReadAll方法,所以重新獲取了一次
   in = multipartFile.getInputStream();
   /*
    * ExcelReaderBuilder中的Sheet方法,需要新增讀取的Sheet名作為引數
    * 並且不要忘記在後面再呼叫一下doReadAll方法,否則不會進行讀取操作
    */

   EasyExcel.read(in,new UploadExcelListener()).doReadAll();
  } catch (IOException e) {
   e.printStackTrace();
  }
  return UploadExcelListener.list;
 }
}

5、application.yml配置

server:
 # 指定埠號
 port: 8080
spring:
 servlet:
 multipart:
  # 配置單個上傳檔案大小
  file-size-threshold: 100M
  # 配置總上傳大小
  max-request-size: 300M

6、測試

我們先搞一個簡單的Excel,用來測試

在這裡插入圖片描述

然後通過Postman模擬傳送請求

  • 選擇Post請求並輸入請求地址
  • 在下面選擇Body
  • Key的框中輸入controller中的請求的方法中的引數,後面的下拉框中選擇File
  • VALUE框中有一個Select File ,點選後選擇自己剛才建立的測試的Excel
  • 最後點選Send傳送請求

在這裡插入圖片描述

返回值如下:

由於我讀了兩次都放在同一個List中返回,所以返回值中有8個物件。

[
 {
  "name": "小黑","age": 25,"id": 1
 },{
  "name": "小白","age": 22,"id": 2
 },{
  "name": "小黃","id": 3
 },{
  "name": "小綠","age": 23,"id": 4
 },{
  "name": "小黑","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,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);
 }

 /**
  * 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,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,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);
 }

 /**
  * 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,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,ReadListener readListener) {
  ExcelReaderBuilder excelReaderBuilder = new ExcelReaderBuilder();
  excelReaderBuilder.file(inputStream);
  if (head != null) {
   excelReaderBuilder.head(head);
  }
  if (readListener != null) {
   excelReaderBuilder.registerReadListener(readListener);
  }
  return excelReaderBuilder;
 }

所有的方法都在這兒了,其實如果看不懂到底應該呼叫哪一個read方法的話,可以以根據自己所能得到的引數來判斷。

四、擴充套件

讀取本地Excel

public static void main(String[] args) {
 EasyExcel.read("C:/Users/Lonely Programmer/Desktop/新建 Microsoft Excel 工作表.xlsx",new UploadExcelListener())
  .doReadAll();
}

讀取本地的Excel和通過InPutStream流讀取的方式是一樣的,只是引數變了,原本傳的是InPutStream流,現在傳的是檔案的絕對路徑。我這裡監聽類和對映實體類都沒有變,和上傳用的是同一個,大家也可以根據需求來設定自己的監聽類與實體類

MultipartFile文件

MultipartFile文件地址:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/multipart/MultipartFile.html

翻譯是通過Google Chrome自帶翻譯外掛進行翻譯的,建議大家使用Google Chrome開啟,自帶翻譯功能

在這裡插入圖片描述

到此這篇關於SpringBoot整合EasyExcel實現Excel匯入的方法的文章就介紹到這了,更多相關SpringBoot實現Excel匯入內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!