Spring Boot 牽手EasyExcel:解鎖高效數據處理姿勢

引言

在日常的 Java 開發中,處理 Excel 文件是一個極為常見的需求。無論是數據的導入導出,還是報表的生成,Excel 都扮演著重要的角色。例如,在企業的財務管理系統中,需要將每月的財務數據導出為 Excel 報表,方便財務人員進行數據分析和審計;在人力資源管理系統中,可能需要導入員工的基本信息、考勤記錄等數據到系統中。

然而,傳統的 Excel 處理方式,如使用 POI 等工具,雖然功能強大,但在面對復雜的業務場景時,往往會顯得力不從心,代碼復雜度較高,開發效率低下。而 EasyExcel 的出現,為我們提供了一種更加便捷、高效的 Excel 處理方案。它是阿里巴巴開源的一款基于 Java 的簡單、快速、省內存的 Excel 處理框架,能讓我們在開發中輕松應對各種 Excel 操作。

結合 Spring Boot 強大的依賴管理和快速開發特性,將 EasyExcel 集成到 Spring Boot 項目中,能夠極大地提高我們開發 Excel 相關功能的效率,讓代碼更加簡潔、易維護。接下來,就讓我們深入探索 Spring Boot 集成 EasyExcel 的常見業務用法吧!

一、準備工作

1.1 搭建 Spring Boot 項目

首先,我們需要搭建一個 Spring Boot 項目。可以通過 Spring Initializr(https://start.spring.io/ )來快速創建項目。在瀏覽器中打開該網址,按照以下步驟進行配置:

  • Group:填寫項目的組名,通常是公司或組織的反向域名,例如com.example。
  • Artifact:填寫項目的名稱,比如spring-boot-easyexcel-demo。
  • Dependencies:添加項目所需的依賴,這里我們至少需要添加Spring Web依賴,用于創建 Web 接口來處理 Excel 相關的請求。

配置完成后,點擊 “Generate” 按鈕,下載生成的項目壓縮包。解壓后,使用 IDE(如 IntelliJ IDEA 或 Eclipse)打開項目。

1.2 添加 EasyExcel 依賴

在項目的pom.xml文件中添加 EasyExcel 的依賴。EasyExcel 是阿里巴巴開源的 Excel 處理框架,添加依賴后,我們就可以使用它提供的豐富功能來操作 Excel 文件。在pom.xml的<dependencies>標簽中添加如下依賴:

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

上述代碼中,<groupId>指定了依賴的組,com.alibaba表示這是阿里巴巴的開源項目;<artifactId>指定了依賴的名稱,easyexcel即我們要引入的 Excel 處理框架;<version>指定了依賴的版本號,這里使用的是3.1.2版本,你可以根據實際情況選擇合適的版本 。添加依賴后,Maven 會自動下載并管理該依賴及其相關的依賴項。

二、基本使用示例

2.1 創建 Excel 實體類

在 Spring Boot 項目中使用 EasyExcel,首先需要創建與 Excel 表格結構對應的實體類。通過@ExcelProperty注解來指定實體類字段與 Excel 表格列的映射關系。例如,我們創建一個User實體類來表示用戶信息:

 
import com.alibaba.excel.annotation.ExcelProperty;import lombok.Data;@Datapublic class User {@ExcelProperty("用戶ID")private Long userId;@ExcelProperty("用戶名")private String username;@ExcelProperty("用戶郵箱")private String email;}

在上述代碼中,@ExcelProperty注解的參數值即為 Excel 表格中的列名。userId字段對應 “用戶 ID” 列,username字段對應 “用戶名” 列,email字段對應 “用戶郵箱” 列 。這樣,在進行 Excel 數據的讀寫操作時,EasyExcel 就能根據這些注解準確地將實體類對象與 Excel 表格中的數據進行映射 。

2.2 數據導出

接下來,我們實現將數據導出為 Excel 文件的功能。在 Spring Boot 中,通常在控制器層編寫導出邏輯。以下是一個導出用戶數據的控制器代碼示例:

 
import com.alibaba.excel.EasyExcel;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.net.URLEncoder;import java.util.ArrayList;import java.util.List;@RestControllerpublic class UserController {@GetMapping("/export")public void exportUser(HttpServletResponse response) throws IOException {// 設置響應頭,告訴瀏覽器這是一個Excel文件下載response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");// 對文件名進行編碼,防止中文亂碼String fileName = URLEncoder.encode("用戶信息表", "UTF-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");// 模擬從數據庫中獲取數據,這里用List來代替List < User > userList = new ArrayList < > ();User user1 = new User();user1.setUserId(1 L);user1.setUsername("張三");user1.setEmail("zhangsan@example.com");userList.add(user1);User user2 = new User();user2.setUserId(2 L);user2.setUsername("李四");user2.setEmail("lisi@example.com");userList.add(user2);// 使用EasyExcel進行導出操作ServletOutputStream outputStream = response.getOutputStream();EasyExcel.write(outputStream, User.class).sheet("用戶信息").doWrite(userList);outputStream.flush();outputStream.close();}}

上述代碼中,@GetMapping("/export")注解表示這是一個處理 GET 請求的方法,路徑為/export。在方法內部,首先設置了響應頭,包括內容類型為 Excel 文件類型,字符編碼為 UTF - 8,并設置了文件名。然后,模擬從數據庫中獲取用戶數據,創建了兩個User對象并添加到userList中。最后,通過EasyExcel.write(outputStream, User.class).sheet("用戶信息").doWrite(userList)這行代碼,將userList中的數據寫入到 Excel 文件中,并通過響應流返回給客戶端。其中,outputStream是響應的輸出流,User.class指定了要寫入的實體類,sheet("用戶信息")設置了 Excel 文件中的工作表名稱 。

2.3 數據導入

數據導入功能需要創建一個監聽器來處理 Excel 文件中的每一行數據。監聽器繼承自AnalysisEventListener類,重寫invoke方法來處理解析到的數據,重寫doAfterAllAnalysed方法來在所有數據解析完成后執行一些操作。以下是導入用戶數據的監聽器代碼示例:

 
import com.alibaba.excel.context.AnalysisContext;import com.alibaba.excel.event.AnalysisEventListener;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.util.ArrayList;import java.util.List;public class UserDataListener extends AnalysisEventListener < User > {private static final Logger LOGGER = LoggerFactory.getLogger(UserDataListener.class);// 用于存儲解析到的數據private List < User > userList = new ArrayList < > ();@Overridepublic void invoke(User user, AnalysisContext context) {LOGGER.info("解析到一條數據:{}", user);userList.add(user);}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {LOGGER.info("所有數據解析完成!");// 這里可以將userList中的數據批量插入到數據庫中}public List < User > getUserList() {return userList;}}

在控制器層,通過EasyExcel.read方法讀取 Excel 文件,并傳入監聽器來處理數據。以下是導入用戶數據的控制器代碼示例:

import com.alibaba.excel.EasyExcel;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.multipart.MultipartFile;import java.io.IOException;@RestControllerpublic class UserImportController {@PostMapping("/import")public String importUser(@RequestParam("file") MultipartFile file) throws IOException {UserDataListener listener = new UserDataListener();EasyExcel.read(file.getInputStream(), User.class, listener).sheet().doRead();// 可以在這里對listener.getUserList()中的數據進行進一步處理return "數據導入成功";}}

上述代碼中,@PostMapping("/import")注解表示這是一個處理 POST 請求的方法,路徑為/import。@RequestParam("file")用于接收前端上傳的 Excel 文件。在方法內部,創建了UserDataListener監聽器,并通過EasyExcel.read(file.getInputStream(), User.class, listener).sheet().doRead()讀取 Excel 文件中的數據,將每一行數據解析為User對象,并由監聽器進行處理。最后返回 “數據導入成功” 的提示信息 。

三、常見業務場景用法

3.1 復雜表頭導出

在實際業務中,Excel 的表頭可能會比較復雜,包含多級表頭的情況。通過@ExcelProperty注解可以很方便地實現復雜表頭的導出。假設我們要導出一份員工績效考核報表,報表包含員工基本信息、考核指標、考核結果等多個層級的表頭 。首先,創建一個對應的實體類EmployeePerformance:

import com.alibaba.excel.annotation.ExcelProperty;import lombok.Data;@Datapublic class EmployeePerformance {@ExcelProperty(index = 0, value = {"員工信息","員工編號"})private Long employeeId;@ExcelProperty(index = 1, value = {"員工信息","員工姓名"})private String employeeName;@ExcelProperty(index = 2, value = {"考核指標","工作完成率"})private Double workCompletionRate;@ExcelProperty(index = 3, value = {"考核指標","工作質量評分"})private Integer workQualityScore;@ExcelProperty(index = 4, value = {"考核結果","最終評級"})private String finalRating;}

在上述實體類中,@ExcelProperty注解的value屬性通過數組的形式定義了多級表頭。例如,{"員工信息", "員工編號"}表示第一級表頭為 “員工信息”,第二級表頭為 “員工編號” 。index屬性用于指定列的順序,從 0 開始 。

接下來,在控制器中編寫導出方法:

 
import com.alibaba.excel.EasyExcel;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.net.URLEncoder;import java.util.ArrayList;import java.util.List;@RestControllerpublic class EmployeePerformanceController {@GetMapping("/exportPerformance")public void exportEmployeePerformance(HttpServletResponse response) throws IOException {response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");String fileName = URLEncoder.encode("員工績效考核報表", "UTF-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");List < EmployeePerformance > performanceList = new ArrayList < > ();// 模擬數據EmployeePerformance performance1 = new EmployeePerformance();performance1.setEmployeeId(1 L);performance1.setEmployeeName("張三");performance1.setWorkCompletionRate(0.95);performance1.setWorkQualityScore(90);performance1.setFinalRating("優秀");performanceList.add(performance1);EmployeePerformance performance2 = new EmployeePerformance();performance2.setEmployeeId(2 L);performance2.setEmployeeName("李四");performance2.setWorkCompletionRate(0.85);performance2.setWorkQualityScore(80);performance2.setFinalRating("良好");performanceList.add(performance2);ServletOutputStream outputStream = response.getOutputStream();EasyExcel.write(outputStream, EmployeePerformance.class).sheet("員工績效考核").doWrite(performanceList);outputStream.flush();outputStream.close();}}

通過上述代碼,訪問/exportPerformance接口,即可下載包含復雜表頭的員工績效考核報表 。

3.2 大數據量處理

當處理大數據量的 Excel 文件時,如果一次性讀取或寫入所有數據,可能會導致內存溢出。因此,需要采用分批讀取和寫入的方式。其原理是通過分頁查詢數據庫,每次獲取一部分數據,然后將這部分數據寫入 Excel 文件中,直到所有數據處理完畢 。

假設我們有一個User表,數據量較大,需要導出所有用戶信息到 Excel 文件中。首先,在數據庫查詢方法中實現分頁查詢。這里以使用 MyBatis-Plus 為例,假設已經配置好了 MyBatis-Plus 的相關依賴和配置 。

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import org.springframework.stereotype.Service;import javax.annotation.Resource;import java.util.List;@Servicepublic class UserService {@Resourceprivate UserMapper userMapper;public List < User > getUserListByPage(int pageNum, int pageSize) {Page < User > page = new Page < > (pageNum, pageSize);QueryWrapper < User > wrapper = new QueryWrapper < > ();return userMapper.selectPage(page, wrapper).getRecords();}}

在上述代碼中,getUserListByPage方法通過Page對象進行分頁查詢,pageNum表示當前頁碼,pageSize表示每頁的數據量 。

然后,在控制器中編寫導出方法,實現分批寫入 Excel:

import com.alibaba.excel.EasyExcel;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.net.URLEncoder;import java.util.List;@RestControllerpublic class UserBigDataExportController {@Resourceprivate UserService userService;@GetMapping("/exportBigData")public void exportBigData(HttpServletResponse response) throws IOException {response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");String fileName = URLEncoder.encode("用戶信息大數據量導出", "UTF-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");ServletOutputStream outputStream = response.getOutputStream();int pageNum = 1;int pageSize = 1000;List < User > userList;do {userList = userService.getUserListByPage(pageNum, pageSize);EasyExcel.write(outputStream, User.class).sheet("用戶信息").doWrite(userList);pageNum++;} while (!userList.isEmpty());outputStream.flush();outputStream.close();}}

在上述代碼中,通過一個do-while循環,不斷分頁查詢數據庫,并將查詢到的數據寫入 Excel 文件中,直到查詢到的用戶列表為空,表示所有數據已處理完畢 。

3.3 數據校驗

在數據導入時,為了保證數據的準確性和完整性,需要對導入的數據進行校驗。可以通過實現Validator接口來進行數據校驗 。

首先,創建一個自定義的校驗注解@ValidUser:

import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.*;@Documented@Constraint(validatedBy = UserValidator.class)@Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE
})@Retention(RetentionPolicy.RUNTIME)public @interface ValidUser {String message() default "用戶數據校驗失敗";Class < ? > [] groups() default {};Class < ? extends Payload > [] payload() default {};}

然后,創建校驗器UserValidator,實現ConstraintValidator接口:

import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;public class UserValidator implements ConstraintValidator < ValidUser, User > {@Overridepublic void initialize(ValidUser constraintAnnotation) {ConstraintValidator.super.initialize(constraintAnnotation);}@Overridepublic boolean isValid(User user, ConstraintValidatorContext context) {if (user == null) {return false;}// 校驗用戶名不為空if (user.getUsername() == null || user.getUsername().isEmpty()) {return false;}// 校驗郵箱格式String emailRegex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$";if (user.getEmail() == null || !user.getEmail().matches(emailRegex)) {return false;}return true;}}

在上述代碼中,UserValidator實現了isValid方法,在該方法中對User對象的用戶名和郵箱進行了校驗 。

最后,在數據導入的監聽器中使用該校驗注解:

import com.alibaba.excel.context.AnalysisContext;import com.alibaba.excel.event.AnalysisEventListener;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.validation.ConstraintViolation;import javax.validation.Validation;import javax.validation.Validator;import java.util.ArrayList;import java.util.List;import java.util.Set;public class UserDataValidatorListener extends AnalysisEventListener < User > {private static final Logger LOGGER = LoggerFactory.getLogger(UserDataValidatorListener.class);private List < User > userList = new ArrayList < > ();private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();@Overridepublic void invoke(User user, AnalysisContext context) {Set < ConstraintViolation < User >> violations = validator.validate(user);if (!violations.isEmpty()) {StringBuilder errorMessage = new StringBuilder("數據校驗失敗: ");for (ConstraintViolation < User > violation: violations) {errorMessage.append(violation.getPropertyPath()).append(" ").append(violation.getMessage()).append("; ");}LOGGER.error(errorMessage.toString());} else {LOGGER.info("解析到一條數據:{}", user);userList.add(user);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {LOGGER.info("所有數據解析完成!");// 這里可以將userList中的數據批量插入到數據庫中}public List < User > getUserList() {return userList;}}

在上述監聽器中,通過Validator對每一個解析到的User對象進行校驗,如果校驗失敗,記錄錯誤信息;如果校驗成功,將數據添加到userList中 。在控制器中使用該監聽器進行數據導入時,就能實現對導入數據的校驗 。

四、注意事項與優化

4.1 日期格式處理

在處理 Excel 中的日期數據時,日期格式的正確處理至關重要。在實體類中,可以使用@DateTimeFormat注解來指定日期格式。例如,如果 Excel 表格中的日期格式為 “yyyy-MM-dd”,在實體類的日期字段上添加如下注解:

import com.alibaba.excel.annotation.ExcelProperty;import org.springframework.format.annotation.DateTimeFormat;import java.util.Date;public class Order {@ExcelProperty("訂單日期")@DateTimeFormat(pattern = "yyyy-MM-dd")private Date orderDate;// 其他字段...}

上述代碼中,@DateTimeFormat(pattern = "yyyy-MM-dd")指定了在將 Excel 中的日期字符串轉換為Date對象時,使用 “yyyy-MM-dd” 的格式進行解析 。同樣,在導出數據時,也會按照此格式將Date對象轉換為字符串寫入 Excel 文件 。

除了使用@DateTimeFormat注解,還可以通過自定義轉換器來處理日期格式。自定義轉換器需要實現Converter接口,重寫convertToJavaData和convertToExcelData方法。例如,創建一個自定義的LocalDateTimeConverter:

 
import com.alibaba.excel.converters.Converter;import com.alibaba.excel.enums.CellDataTypeEnum;import com.alibaba.excel.metadata.GlobalConfiguration;import com.alibaba.excel.metadata.data.ReadCellData;import com.alibaba.excel.metadata.data.WriteCellData;import com.alibaba.excel.metadata.property.ExcelContentProperty;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;public class LocalDateTimeConverter implements Converter < LocalDateTime > {@Overridepublic Class < LocalDateTime > supportJavaTypeKey() {return LocalDateTime.class;}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}@Overridepublic LocalDateTime convertToJavaData(ReadCellData < ? > cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {String value = cellData.getStringValue();return LocalDateTime.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));}@Overridepublic WriteCellData < ? > convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {return new WriteCellData < > (value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));}}

在實體類中使用自定義轉換器:

import com.alibaba.excel.annotation.ExcelProperty;import java.time.LocalDateTime;public class Event {@ExcelProperty(value = "活動時間", converter = LocalDateTimeConverter.class)private LocalDateTime eventTime;// 其他字段...}

通過自定義轉換器,可以更靈活地處理各種復雜的日期格式,滿足不同業務場景的需求 。

4.2 內存優化

當處理大數據量的 Excel 文件時,內存優化是一個關鍵問題。如果一次性讀取或寫入大量數據,可能會導致內存溢出,使系統崩潰或性能急劇下降 。

使用監聽器結合分頁處理是一種有效的內存優化策略。在數據導入時,監聽器可以逐行讀取 Excel 數據,而不是一次性加載整個文件到內存中。例如,在之前的數據導入監聽器UserDataListener基礎上,結合分頁處理數據庫插入操作:

import com.alibaba.excel.context.AnalysisContext;import com.alibaba.excel.event.AnalysisEventListener;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.util.ArrayList;import java.util.List;public class UserDataListener extends AnalysisEventListener < User > {private static final Logger LOGGER = LoggerFactory.getLogger(UserDataListener.class);private List < User > userList = new ArrayList < > ();private static final int BATCH_SIZE = 1000;@Overridepublic void invoke(User user, AnalysisContext context) {userList.add(user);if (userList.size() >= BATCH_SIZE) {saveData();userList.clear();}}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {if (!userList.isEmpty()) {saveData();}LOGGER.info("所有數據解析完成!");}private void saveData() {// 這里實現將userList中的數據批量插入到數據庫的邏輯// 例如使用MyBatis-Plus的批量插入方法// userMapper.insertBatch(userList);LOGGER.info("批量插入數據到數據庫,數據量:{}", userList.size());}}

在上述代碼中,invoke方法每解析一行數據就添加到userList中,當userList的大小達到BATCH_SIZE(這里設置為 1000)時,調用saveData方法將數據批量插入到數據庫,并清空userList,釋放內存 。在doAfterAllAnalysed方法中,處理剩余未插入的數據 。

在數據導出時,同樣可以采用分頁查詢數據庫,分批寫入 Excel 的方式。如之前大數據量處理部分的示例代碼,通過do-while循環不斷分頁查詢數據庫,并將查詢到的數據寫入 Excel 文件中,每次只處理一小部分數據,避免內存占用過高 。

4.3 異常處理

在 Excel 的導出和導入過程中,可能會出現各種異常,如文件讀取失敗、數據格式轉換錯誤等。為了保證系統的穩定性和用戶體驗,捕獲異常并返回友好提示是非常重要的 。

在導出數據時,對可能出現的IOException等異常進行捕獲處理。例如,在之前的導出用戶數據的控制器方法exportUser中添加異常處理:

import com.alibaba.excel.EasyExcel;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.net.URLEncoder;import java.util.ArrayList;import java.util.List;@RestControllerpublic class UserController {@GetMapping("/export")public void exportUser(HttpServletResponse response) {try {response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");String fileName = URLEncoder.encode("用戶信息表", "UTF-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");List < User > userList = new ArrayList < > ();// 模擬數據User user1 = new User();user1.setUserId(1 L);user1.setUsername("張三");user1.setEmail("zhangsan@example.com");userList.add(user1);User user2 = new User();user2.setUserId(2 L);user2.setUsername("李四");user2.setEmail("lisi@example.com");userList.add(user2);ServletOutputStream outputStream = response.getOutputStream();EasyExcel.write(outputStream, User.class).sheet("用戶信息").doWrite(userList);outputStream.flush();outputStream.close();} catch (IOException e) {e.printStackTrace();// 返回友好的錯誤提示給前端response.setContentType("text/plain;charset=utf-8");try {response.getWriter().write("導出文件失敗,請聯系管理員");} catch (IOException ex) {ex.printStackTrace();}}}}

在上述代碼中,使用try-catch塊捕獲IOException異常,在catch塊中,首先打印異常堆棧信息,便于開發人員定位問題;然后設置響應內容類型為純文本,并向客戶端返回 “導出文件失敗,請聯系管理員” 的錯誤提示 。

在數據導入時,同樣需要對異常進行處理。在之前的數據導入控制器方法importUser中添加異常處理:

import com.alibaba.excel.EasyExcel;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.multipart.MultipartFile;import java.io.IOException;@RestControllerpublic class UserImportController {@PostMapping("/import")public String importUser(@RequestParam("file") MultipartFile file) {try {UserDataListener listener = new UserDataListener();EasyExcel.read(file.getInputStream(), User.class, listener).sheet().doRead();return "數據導入成功";} catch (IOException e) {e.printStackTrace();return "數據導入失敗,請檢查文件格式或聯系管理員";}}}

在這個方法中,捕獲IOException異常,返回 “數據導入失敗,請檢查文件格式或聯系管理員” 的提示信息,幫助用戶快速定位問題 。通過合理的異常處理,可以提高系統的健壯性和用戶友好性 。

五、總結

通過本文的介紹,我們深入了解了 Spring Boot 集成 EasyExcel 在常見業務中的用法。從基礎的數據導入導出,到復雜表頭導出、大數據量處理以及數據校驗等場景,EasyExcel 都展現出了強大的功能和便捷性。它不僅簡化了 Excel 操作的代碼編寫,還在性能和內存管理方面表現出色,尤其適用于處理大數據量的 Excel 文件。

在實際項目中,合理運用 Spring Boot 集成 EasyExcel,可以大大提高開發效率,優化系統性能。無論是企業級應用中的報表生成、數據備份與恢復,還是數據分析平臺的數據預處理等場景,都能發揮其優勢。同時,通過對日期格式處理、內存優化和異常處理等方面的注意和優化,能夠使我們的應用更加健壯和穩定。

希望讀者通過本文的學習,能夠掌握 Spring Boot 集成 EasyExcel 的技巧,并在實際項目中靈活運用,解決各種 Excel 處理相關的問題,提升項目的質量和用戶體驗。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/87950.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87950.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87950.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【ARM AMBA AXI 入門 21 -- AXI partial 訪問和 narrow 訪問的區別】

文章目錄 Overview一、定義區別二、AXI 信號層面對比三、舉例說明示例一:Partial Access示例二:Narrow Access四、硬件/系統處理角度五、AXI 總線接口信號舉例對比Partial Write 事務:Narrow Write 事務(32-bit Master on 64-bit Bus):六、總結對比表七,軟件判斷判斷 Pa…

使用Ideal創建一個spring boot的helloWorld項目

說明&#xff1a;本篇將介紹如何使用Ideal2024.2.1去創建一個spring boot的helloWorld項目&#xff0c;本篇將包含創建的詳細步驟以及spring boot項目的目錄結構說明&#xff0c;創建過程中的選項說明等。詳細步驟如下&#xff1a;第一步&#xff1a;點擊文件——新建——項目&…

國內Ubuntu訪問不了github等外網

各位小伙伴們&#xff0c;大家好呀。 大家是不是經常遇到訪問不了外網的情況呀。 在Ubuntu中可以這樣做。 訪問這個網站網站測速-Ping檢測-Trace查詢-Dig查詢-路由跟蹤查詢-tools.ipip.net&#xff0c; 對于github.com&#xff0c;在這個網站輸入github.com&#xff0c;會返…

PDF轉換工具,即開即用

在辦公室里&#xff0c;這句話被反復驗證。每天面對成堆的Word和Excel文件&#xff0c;將它們轉換成PDF格式是常有的事。可之前用過的工具&#xff0c;不是一次只能轉一個&#xff0c;就是操作繁瑣得讓人頭疼。記得有次趕項目&#xff0c;需要把二十多個文檔轉成PDF&#xff0c…

2. 你可以說一下 http 版本的發展過程嗎

你可以說一下 http 版本的發展過程嗎 總結&#xff1a;0.9&#xff1a;只能發送 get&#xff0c;無狀態。1.0&#xff1a;新增 post&#xff0c;請求頭&#xff0c;狀態碼&#xff0c;cookie。1.1&#xff1a;新增 put/delete/options/patch&#xff0c;keep-alive&#xff0c…

04-Linux驅動模塊的自動加載

概述 上一節&#xff0c;我們講述了Linux驅動開發的基本的模塊代碼編寫和手動執行模塊加載的操作&#xff0c; 這一節&#xff0c;我們講述嵌入式設備上使用Sysvint引導方式下如何開機自動加載模塊的步驟。感興趣的同學看下使用systemd引導方式的開啟自動加載模塊的步驟 操作…

【牛客算法】游游的整數切割

文章目錄 一、題目介紹1.1 題目鏈接1.2 題目描述1.3 輸入描述1.4 輸出描述1.5 示例二、解題思路2.1 核心算法設計2.2 性能優化關鍵2.3 算法流程圖三、解法實現3.1 解法一:基礎遍歷法3.1.1 初級版本分析3.2 解法二:奇偶預統計法(推薦)3.2.1 優化版本分析四、總結與拓展4.1 關…

筆記本電腦忽亮忽暗問題

關于筆記本電腦忽亮忽暗的問題這個問題困擾了我大半年&#xff0c;最后忽然找到解決方法了---主要的話有三種可能性1.關閉顯示器自動調亮的功能2.關閉節能模式自動調亮功能3.調整顯卡的功率&#xff0c;關閉自動調亮功能一開始一直都是嘗試的第一種方法&#xff0c;沒解決。。。…

Qt的頂部工具欄在多個界面使用

Qt的工具欄在多個界面使用1、前言2、創建一個工具欄類2.1 新建一個工具欄類3、提升工具欄類3.1登錄界面添加工具欄3.2 創建工具欄對象4、總結1、前言 今天遇到了個問題&#xff0c;頂部的工具欄&#xff0c;像軟鍵盤&#xff0c;時間顯示和退出按鈕那些&#xff0c;想在多個界…

C#和SQL Server連接常用通訊方式

C#和SQL Server連接通訊 在 C# 中與 SQL Server 建立數據庫連接&#xff0c;主要通過 ADO.NET 技術實現。以下是幾種常見的連接方式及相關實踐&#xff1a; ADO.NET 全面指南&#xff1a;C# 數據庫訪問核心技術 ADO.NET 是 .NET Framework 中用于數據訪問的核心組件&#xf…

安卓10.0系統修改定制化____實現自動開啟 USB 調試?的步驟解析 列舉常用的幾種修改方法

對于安卓開發者、測試人員,甚至是喜歡折騰手機的數碼愛好者來說,USB 調試是一個非常重要的功能。它能讓手機與電腦相連,實現應用安裝、系統調試、數據傳輸等操作。但每次連接手機都要手動去設置里開啟 USB 調試,實在麻煩。其實,通過修改安卓 10.0 的 ROM,就能讓手機自動開…

Redisson詳細教程 - 從入門到精通

目錄 1. 什么是Redisson 2. 為什么要用Redisson 3. 環境準備和配置 4. 基礎使用方法 5. 分布式數據結構 6. 分布式鎖詳解 7. 分布式服務 8. 實際應用場景 9. 最佳實踐 10. 常見問題解答 總結 1. 什么是Redisson 簡單理解 想象一下,Redis就像一個超級強大的"內…

動態規劃VS記憶化搜索(2)

luoguP1434滑雪 題目描述 Michael 喜歡滑雪。這并不奇怪&#xff0c;因為滑雪的確很刺激。可是為了獲得速度&#xff0c;滑的區域必須向下傾斜&#xff0c;而且當你滑到坡底&#xff0c;你不得不再次走上坡或者等待升降機來載你。Michael 想知道在一個區域中最長的滑坡。區域由…

如何將服務守護進程化

進程組 什么是進程組 之前我們提到了進程的概念&#xff0c; 其實每一個進程除了有一個進程 ID(PID)之外 還屬于一個進程組。進程組是一個或者多個進程的集合&#xff0c; 一個進程組可以包含多個進程。 每一個進程組也有一個唯一的進程組 ID(PGID)&#xff0c; 并且這個 PGID …

【跟著PMP學習項目管理】項目管理 之 范圍管理知識點

目錄 一、收集需求 1、知識點匯總 2、輸入 3、工具 4、輸出 二、定義范圍 1、知識點匯總 2、輸入 3、工具 4、輸出 三、創作工作分解結構 1、知識點匯總 2、輸入 3、工具 4、輸出 四、核實范圍 1、知識點匯總 2、輸入 3、工具 4、輸出 五、控制范圍 1、知…

AIX 環境磁盤空間管理指南

AIX 環境磁盤空間管理指南 在AIX環境中&#xff0c;磁盤空間的監控、管理與擴展是運維人員必備的技能。本文通過實際案例&#xff0c;系統地介紹如何查詢磁盤信息、卷組(VG)、邏輯卷(LV)信息&#xff0c;以及在磁盤空間不足時的擴容方案&#xff0c;幫助讀者掌握磁盤空間管理的…

k8s將service的IP對應的不同端口分配到不同的pod上

在Kubernetes中&#xff0c;Service是一種抽象層&#xff0c;它將請求路由到一組Pod。當你需要將Service的不同端口映射到不同的Pod時&#xff0c;可以通過以下兩種主要方式實現&#xff1a; 方法一&#xff1a;使用單個Service的多端口配置 如果不同的Pod提供不同的服務&…

aic8800M40低功耗sdio wifi在arm-linux平臺調試經驗

背景 好多年沒有搞過wifi相關的內容了,最近也被安排上了,把一顆低功耗aic8800M40的芯片在arm-linux開發板上做bring up,記錄一下SDIO wifi調試的過程和經驗,SDIO驅動這里需要改動一些linux內核HOST驅動代碼,會在文章中貼出來: AIC8800M40芯片簡介 這個wifi芯片是一顆低…

Redis基礎(1):NoSQL認識

SQL和NoSQL數據庫可以分為關系型數據庫和非關系型數據庫&#xff0c;SQL(Structured Query Language)相信大家并不陌生&#xff0c;這是用于操作關系型數據庫的語言&#xff0c;而NoSQL&#xff0c;顧名思義&#xff0c;它對應的就是非關系數據庫&#xff0c;它是操作非關系型數…

QT6 源(153)模型視圖架構里的表格窗體視圖 QTableWidget 篇三:源碼及其元素 QTableWidgetItem 的源代碼帶注釋

&#xff08;14&#xff09;本源代碼定義于頭文件 qtablewidget . h 頭文件 &#xff1a; #ifndef QTABLEWIDGET_H #define QTABLEWIDGET_H#include <QtWidgets/qtableview.h> #include <QtWidgets/qtwidgetsglobal.h> #include <QtCore/qlist.h> #include …