精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Spring Boot 3.4 一鍵搞定!接口實現任意表的 Excel 導入導出

開發 前端
本文展示了一種高效且內存友好的 Excel 文件處理方案。無論是單一表格的導入導出,還是動態適配不同數據表的需求,我們都可以通過泛型和反射機制靈活實現。

在 Java Web 開發中,處理 Excel 文件的導入導出是常見且重要的需求,尤其是在大數據量的場景下,如何高效、安全地進行 Excel 文件的讀寫,直接影響到系統的性能與穩定性。傳統的工具如 EasyPoi 或 Hutool 提供了強大的功能,但在大規模數據處理時,這些工具常常面臨內存溢出(OOM)等性能瓶頸。為了解決這些問題,我們可以轉而使用 EasyExcel,它采用了低內存消耗的設計,能夠高效地處理海量數據的導入導出。

本文將介紹如何通過結合 Spring Boot 3.4 與 EasyExcel,實現一鍵搞定任意表的 Excel 導入導出。我們將通過使用 Java 8 的函數式編程特性、反射機制、以及多線程優化技術,進一步提升開發效率并確保系統的穩定性。特別地,在處理大數據量時,我們會通過批量存儲和線程池的方式,避免內存溢出問題,并進一步優化導入導出的性能。

優化策略

  1. 使用 Java 8 的函數式編程簡化數據導入
  2. 利用反射實現通用接口導入任意 Excel
  3. 通過線程池優化大數據量 Excel 導入性能
  4. 通過泛型支持多種數據導出格式

Maven 依賴

首先,需要在 pom.xml 文件中添加 EasyExcel 的依賴:

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

使用泛型實現對象的單個 Sheet 導入

首先,我們創建一個用于表示導入數據的類,假設是一個學生信息類:

package com.icoderoad.entity;


import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("stu_info")
@ApiModel("學生信息")
public class StuInfo {


    private static final long serialVersionUID = 1L;


    @ApiModelProperty("姓名")
    @ExcelProperty(value = "姓名", order = 0)
    private String name;


    @ApiModelProperty("年齡")
    @ExcelProperty(value = "年齡", order = 1)
    private Integer age;


    @ApiModelProperty("身高")
    @ExcelProperty(value = "身高", order = 2)
    private Double tall;


    @ApiModelProperty("自我介紹")
    @ExcelProperty(value = "自我介紹", order = 3)
    private String selfIntroduce;


    @ApiModelProperty("性別")
    @ExcelProperty(value = "性別", order = 4)
    private Integer gender;


    @ApiModelProperty("入學時間")
    @ExcelProperty(value = "入學時間", order = 5)
    private String intake;


    @ApiModelProperty("出生日期")
    @ExcelProperty(value = "出生日期", order = 6)
    private String birthday;
}

重寫 ReadListener 接口

為了處理數據導入過程中可能出現的內存溢出問題,我們重寫 ReadListener 接口,并將數據按批次進行存儲:

package com.icoderoad.listener;


import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.read.listener.ReadListener;
import com.icoderoad.exception.BizException;
import lombok.extern.slf4j.Slf4j;


import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;


@Slf4j
public class UploadDataListener<T> implements ReadListener<T> {


    private static final int BATCH_COUNT = 100;
    private List<T> cachedDataList = new ArrayList<>(BATCH_COUNT);
    private Predicate<T> predicate;
    private Consumer<Collection<T>> consumer;


    public UploadDataListener(Predicate<T> predicate, Consumer<Collection<T>> consumer) {
        this.predicate = predicate;
        this.consumer = consumer;
    }


    public UploadDataListener(Consumer<Collection<T>> consumer) {
        this.consumer = consumer;
    }


    @Override
    public void invoke(T data, AnalysisContext context) {
        if (predicate != null && !predicate.test(data)) {
            return;
        }
        cachedDataList.add(data);


        // When the batch size reaches BATCH_COUNT, trigger data storage
        if (cachedDataList.size() >= BATCH_COUNT) {
            try {
                consumer.accept(cachedDataList);
            } catch (Exception e) {
                log.error("Data upload failed! Data={}", cachedDataList);
                throw new BizException("Import failed");
            }
            cachedDataList.clear();
        }
    }


    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        if (!cachedDataList.isEmpty()) {
            try {
                consumer.accept(cachedDataList);
                log.info("All data parsing completed!");
            } catch (Exception e) {
                log.error("Data upload failed! Data={}", cachedDataList);
                if (e instanceof BizException) {
                    throw e;
                }
                throw new BizException("Import failed");
            }
        }
    }
}

Controller 層實現

在 Controller 層,我們使用 EasyExcel.read() 方法讀取上傳的文件,并通過 UploadDataListener 實現數據批量存儲:

package com.icoderoad.controller;


import com.alibaba.excel.EasyExcel;
import com.icoderoad.entity.StuInfo;
import com.icoderoad.listener.UploadDataListener;
import com.icoderoad.service.StuInfoService;
import com.icoderoad.util.ValidationUtils;
import com.icoderoad.exception.BizException;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;


import java.io.IOException;


@Slf4j
@RestController
@RequestMapping("/excel")
public class ExcelController {


    @Autowired
    private StuInfoService service;


    @ApiOperation("一鍵導入數據到 Excel")
    @PostMapping("/update")
    @ResponseBody
    public R<String> importExcel(MultipartFile file) throws IOException {
        try {
            EasyExcel.read(file.getInputStream(), StuInfo.class, new UploadDataListener<StuInfo>(
                list -> {
                    // 驗證數據
                    ValidationUtils.validate(list);
                    // 批量保存數據
                    service.saveBatch(list);
                    log.info("Imported {} rows of data from Excel", list.size());
                }
            )).sheet().doRead();
        } catch (IOException e) {
            log.error("Import failed", e);
            throw new BizException("Import failed");
        }
        return R.success("Success");
    }
}

處理任意數據表的導入

對于需要導入不同數據表的情況,我們可以通過傳遞表編碼以及文件來動態讀取數據,并進行適配:

@ApiOperation("通用數據表導入")
@PostMapping("/listenMapData")
@ResponseBody
public R<String> listenMapData(@RequestParam("tableCode") String tableCode, MultipartFile file) throws IOException {
    try {
        EasyExcel.read(file.getInputStream(), new NonClazzOrientedListener(
            list -> {
                log.info("Imported {} rows of data", list.size());
            }
        )).sheet().doRead();
    } catch (IOException e) {
        log.error("Import failed", e);
        throw new BizException("Import failed");
    }
    return R.success("Success");
}

重寫 ReadListener 接口處理非類型化數據

當我們需要處理不同類型的表時,可以通過 Map 來處理數據,具體實現如下:

package com.icoderoad.listener;


import com.alibaba.excel.context.AnalysisContext;
import com.icoderoad.exception.BizException;
import lombok.extern.slf4j.Slf4j;


import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Predicate;


@Slf4j
public class NonClazzOrientedListener implements ReadListener<Map<Integer, String>> {


    // 定義批次處理的大小
    private static final int BATCH_COUNT = 100;


    // 用于緩存行數據
    private List<List<Object>> rowsList = new ArrayList<>(BATCH_COUNT);


    // 臨時存儲每一行數據
    private List<Object> rowList = new ArrayList<>();


    // 條件判斷的 Predicate,決定是否處理當前行
    private Predicate<Map<Integer, String>> predicate;


    // 數據處理的消費者
    private Consumer<List> consumer;


    // 構造函數,傳入條件判斷和數據處理邏輯
    public NonClazzOrientedListener(Predicate<Map<Integer, String>> predicate, Consumer<List> consumer) {
        this.predicate = predicate;
        this.consumer = consumer;
    }


    // 構造函數,只傳入數據處理邏輯
    public NonClazzOrientedListener(Consumer<List> consumer) {
        this.consumer = consumer;
    }


    @Override
    public void invoke(Map<Integer, String> row, AnalysisContext analysisContext) {
        // 判斷是否符合處理條件,如果有定義 Predicate,進行過濾
        if (predicate != null && !predicate.test(row)) {
            return;
        }


        // 清理 rowList,為下一行做準備
        rowList.clear();


        // 處理每一行的數據,將行數據添加到 rowList
        row.forEach((k, v) -> {
            log.debug("處理數據行,鍵:{},值:{}", k, v);  // 中文日志輸出
            rowList.add(v == null ? "" : v);
        });


        // 將處理過的 rowList 添加到 rowsList
        rowsList.add(rowList);


        // 當達到批次大小時,執行存儲操作
        if (rowsList.size() >= BATCH_COUNT) {
            processBatch();
        }
    }


    // 批量處理數據,并清理緩存
    private void processBatch() {
        try {
            log.debug("執行存儲邏輯,當前批次包含 {} 行數據", rowsList.size());  // 中文日志輸出
            log.info("當前數據:{}", rowsList);
            consumer.accept(rowsList);
        } catch (Exception e) {
            log.error("數據上傳失敗!數據:{}", rowsList, e);  // 中文日志輸出
            if (e instanceof BizException) {
                throw e;
            }
            throw new BizException("導入失敗");
        } finally {
            // 批次處理后清空緩存
            rowsList.clear();
        }
    }


    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 如果還有剩余數據沒有處理,執行最后一次存儲操作
        if (!rowsList.isEmpty()) {
            processBatch();
        }
        log.debug("所有數據處理并上傳完成。");  // 中文日志輸出
    }
}

結論

通過 EasyExcel 和 Spring Boot 3.4 的完美結合,本文展示了一種高效且內存友好的 Excel 文件處理方案。無論是單一表格的導入導出,還是動態適配不同數據表的需求,我們都可以通過泛型和反射機制靈活實現。同時,利用線程池的方式優化大數據量處理,顯著提高了性能,避免了內存溢出(OOM)問題。通過本文的方法,你可以輕松實現任意表的數據導入導出,滿足各種業務需求,并為未來的大規模數據處理奠定堅實的基礎。

優化后的這兩部分旨在加強對文章主題的深入闡述,同時突出技術的實際應用價值和解決方案的優勢,增強文章的專業性和實踐性。如果你覺得還有其他可以進一步擴展或調整的地方,隨時告訴我!

責任編輯:武曉燕 來源: 路條編程
相關推薦

2025-03-26 00:35:00

Javaweb開發

2025-04-08 01:00:00

Spring開發系統

2025-10-31 07:42:31

SpringExcel工具

2021-04-23 10:38:52

Spring BootSpringMVC源碼

2025-09-11 08:07:24

2025-03-28 07:56:39

Spring服務配置

2020-03-31 15:03:56

Spring Boot代碼Java

2025-02-17 00:00:45

接口支付寶沙箱

2025-04-17 04:00:00

2025-09-26 02:00:00

Spring接口開發

2024-10-17 11:09:46

2025-04-08 08:01:31

2022-06-06 08:42:04

spring-boo開發接口防盜刷

2025-07-07 07:33:31

2025-04-27 03:00:00

Spring集成測試

2025-03-03 08:00:00

SpringBootEasyExcel數據導出

2021-05-14 06:15:48

SpringAware接口

2025-11-04 07:58:20

SpringBoot多語言18n

2022-08-01 07:02:06

SpringEasyExcel場景

2024-08-05 09:51:00

點贊
收藏

51CTO技術棧公眾號

国产亚洲欧美一区二区三区| 欧美国产高跟鞋裸体秀xxxhd| 国产日韩一区二区在线观看| 中文字幕在线观看91| 中文字幕在线观看播放| 成人晚上爱看视频| 国产精品成人品| 欧美成人精品一区二区免费看片| 全球av集中精品导航福利| 欧美日韩亚洲综合| 黄色一级在线视频| 乱人伦中文视频在线| 91污在线观看| 97超碰人人看人人 | 91高清视频免费观看| 国产精品视频在| 女仆av观看一区| 日韩一卡二卡三卡| 久久久精品三级| 99riav视频在线观看| 国产精品看片你懂得| 久久大片网站| 国产福利免费视频| 蜜臀久久久久久久| 欧美在线视频a| 精品小视频在线观看| 色乱码一区二区三区网站| 亚洲激情视频在线播放| 亚洲成人av免费观看| 免费成人高清在线视频| 日韩欧中文字幕| 亚洲熟妇无码一区二区三区| 国产二区三区在线| 国产精品久久久久一区二区三区共| 久久精品国产精品青草色艺| 亚洲第一精品网站| 国内精品不卡在线| 成人观看高清在线观看免费| 最近中文字幕免费在线观看| 视频一区视频二区在线观看| 欧美影院久久久| 日本三级免费看| 国产尤物精品| 欧美日韩国产成人在线观看| 亚洲国产精品免费在线观看| 97久久视频| 色爱av美腿丝袜综合粉嫩av| 精品国产aaa| 教室别恋欧美无删减版| 亚洲人午夜色婷婷| 无码一区二区三区在线| 日韩精品免费一区二区三区竹菊| 亚洲高清色综合| 亚洲一区二区三区四区av| 日韩不卡在线视频| 日韩精品综合一本久道在线视频| 欧美性受xxxxxx黑人xyx性爽| 国语自产精品视频在线看抢先版结局| 欧美伊人久久大香线蕉综合69 | xxxxx性欧美特大| 天天综合天天做天天综合| 亚洲色成人一区二区三区小说| 日韩理论视频| 欧美午夜不卡在线观看免费| 欧美午夜精品理论片| 精品视频在线播放一区二区三区| 日韩精品一区二区在线| 成年女人免费视频| 午夜欧洲一区| 中文字幕亚洲欧美日韩在线不卡 | 一二三四社区欧美黄| 妞干网在线播放| 涩涩视频在线播放| 欧美性一级生活| 午夜国产福利在线观看| 欧州一区二区三区| 亚洲国产精品电影| 女女互磨互喷水高潮les呻吟| 成人看的羞羞网站| 欧美日韩第一视频| 在线观看免费av片| 麻豆成人免费电影| 国产精品jizz视频| 麻豆国产在线播放| 玉足女爽爽91| 久久久久人妻精品一区三寸| 香蕉久久久久久| 亚洲精品一区二区精华| 国产亚洲精品熟女国产成人| 99国产**精品****| 午夜精品视频在线| 一区二区视频免费| 菠萝蜜视频在线观看一区| 视频一区不卡| 国模雨婷捆绑高清在线| 在线观看亚洲精品| 日本精品一二三| blacked蜜桃精品一区| 欧美精品一区二区免费| 黄色av一级片| 国产成人日日夜夜| 日韩精品一区二区三区四区五区| 污片视频在线免费观看| 色婷婷一区二区三区四区| 在线视频观看一区二区| 久久不见久久见国语| 欧美成人在线网站| 波多野结衣电车痴汉| 成人网男人的天堂| 免费成人深夜夜行网站视频| 中文在线免费二区三区| 51午夜精品国产| 国产福利短视频| 欧美黄色aaaa| 国产精品专区h在线观看| 三级av在线播放| 夜夜嗨av一区二区三区四季av| 情侣黄网站免费看| 欧美精品中文字幕亚洲专区| 久久精品人人爽| 这里只有精品999| 99久久99久久免费精品蜜臀| 国产精品88久久久久久妇女 | 97超碰人人看人人| av网在线观看| 色狠狠av一区二区三区| 日本一区二区在线免费观看| 中文字幕免费精品| 国产精品视频yy9099| 天堂av在线资源| 亚洲欧美激情插| 日日干日日操日日射| 欧美午夜精品一区二区三区电影| 97视频在线观看视频免费视频| aaa级黄色片| 自拍av一区二区三区| 91热这里只有精品| 国产欧美日韩精品一区二区免费| 久久久免费电影| 免费av一级片| 一区二区三区高清不卡| www.久久com| 一区二区三区国产精华| 成人网在线视频| 男人资源在线播放| 91精品综合久久久久久| 国产喷水在线观看| 久久99日本精品| 国产美女视频免费| 91精品网站在线观看| 久久精品美女视频网站| 国产毛片久久久久| 中文字幕在线观看不卡视频| 九九热99视频| 我不卡伦不卡影院| 91九色极品视频| 国产福利在线免费观看| 欧美精品一区二区三区久久久| 久久久全国免费视频| 成人av网址在线| 日本福利视频在线| 五月综合久久| 国产伦精品免费视频| 欧美日韩视频在线播放| 欧美一区国产二区| 国产91av视频| av一区二区不卡| av无码精品一区二区三区| 日韩激情一区| 99电影在线观看| 黄色激情在线播放| 国产一区二区三区18| 国产一区二区小视频| 亚洲影视资源网| wwwwww日本| 国内久久精品视频| 国产精品无码av在线播放| 国产欧美亚洲精品a| 亚洲free嫩bbb| heyzo高清国产精品| 亚洲一级一级97网| 亚洲黄色在线免费观看| 色婷婷精品久久二区二区蜜臂av | 日韩国产欧美一区二区| 成人在线视频电影| 欧美xnxx| 久久久久亚洲精品| 1024国产在线| 日韩免费一区二区| 销魂美女一区二区| 亚洲女同ⅹxx女同tv| 大地资源二中文在线影视观看 | 国产高清视频在线| 日韩一区二区三区精品视频| 日本中文字幕第一页| 亚洲三级久久久| 少妇毛片一区二区三区| 国产在线播放一区三区四| 成人综合视频在线| 91成人国产| 日本最新一区二区三区视频观看| 网站一区二区| 国产精品女人网站| 久草在线资源福利站| www.亚洲一区| 毛片在线播放网站| 亚洲精品在线观| 国产又粗又黄又爽| 在线亚洲+欧美+日本专区| 久草免费在线视频观看| 中文字幕第一区综合| 屁屁影院国产第一页| 国内欧美视频一区二区| 成人性生生活性生交12| 亚洲精品一级| 黄色网络在线观看| 久久密一区二区三区| 久久手机视频| 国内自拍欧美| 91精品国产99久久久久久红楼| 激情欧美一区二区三区黑长吊| 5566成人精品视频免费| 国内小视频在线看| 欧美成人免费网| 九七久久人人| 久久精品国产69国产精品亚洲| 国产永久免费高清在线观看视频| 亚洲成人久久久| www国产在线| 欧美一区二区黄色| 国产精品久久免费| 欧美情侣在线播放| 中文字幕一区二区免费| 在线欧美日韩精品| 精品人妻一区二区三区免费看| 亚洲成人7777| 国产午夜免费视频| 亚洲一二三四在线观看| 国产这里有精品| 一区二区三区蜜桃| 美女毛片在线观看| 一区二区三区不卡视频| 欧美成人精品欧美一| 亚洲在线视频免费观看| 久久久久久久极品内射| 亚洲一区二区三区视频在线| 久久综合色综合| 亚洲成人免费在线观看| 国产污污视频在线观看| 欧美日韩激情小视频| 日日噜噜噜噜人人爽亚洲精品| 色哟哟一区二区| 中文字幕你懂的| 欧美高清视频一二三区 | 无码免费一区二区三区| 色av一区二区| 一二三四区在线| 欧美一三区三区四区免费在线看 | 在线观看污污网站| 色爱区综合激月婷婷| 亚洲性生活大片| 欧美一区二区三区视频| 亚洲欧美另类综合| 亚洲欧美www| 日本在线观看| 欧美极品美女视频网站在线观看免费| 波多野结衣在线观看| 国产91精品黑色丝袜高跟鞋| 色综合天天色| 91视频免费网站| 东京久久高清| 色播亚洲婷婷| 亚洲有吗中文字幕| 久久视频这里有精品| 免费在线视频一区| 国产成人精品一区二区在线小狼| 99国产精品久久久久久久久久| 女人又爽又黄免费女仆| 中文字幕一区二区三区精华液| 黄色一级视频在线观看| 欧美日韩亚洲视频一区| 波多野结衣一区二区三区四区| 91精品免费观看| 日韩欧美在线观看一区二区| 中文字幕一区电影| www.综合网.com| 国产精品入口夜色视频大尺度 | 麻豆精品视频在线| 手机免费看av片| 中文av一区特黄| 亚洲国产精品成人无久久精品| 精品视频在线看| 手机看片福利永久| 久久精品国产亚洲一区二区| 欧美激情护士| 666精品在线| 欧美久久精品一级c片| 97中文字幕在线| 精品一区二区三区在线观看 | 欧美激情资源网| 久久久美女视频| 在线电影国产精品| 欧美女v视频| 久久久久久尹人网香蕉| 欧美黄色a视频| 欧美日韩国产综合在线| 欧美日韩四区| 国产福利在线免费| 久久久久久久久久久久久夜| 久久国产精品波多野结衣av| 欧美日韩免费观看一区三区| 天天操天天干天天爽| 九九久久国产精品| 视频欧美精品| 三级三级久久三级久久18| 亚洲综合国产| 国产 xxxx| 一区二区三区在线看| 97成人免费视频| 一个人www欧美| 中文字幕在线视频久| 国产精品久久亚洲| 欧美在线三级| 黄色a级三级三级三级| 中文字幕国产精品一区二区| 欧美一区二区三区不卡视频| 亚洲国产精品字幕| 爱看av在线入口| 91九色视频在线观看| 婷婷另类小说| 第四色婷婷基地| 中文字幕精品在线不卡| 亚洲av无码不卡| 亚洲欧美综合v| 伊人久久视频| 欧美精品欧美精品系列c| 亚洲深夜福利| 欧美肉大捧一进一出免费视频| 亚洲综合区在线| 精品黑人一区二区三区在线观看| 久久成人亚洲精品| 精品国产鲁一鲁****| 强开小嫩苞一区二区三区网站 | 国内一区二区三区| 欧美日韩一区二区区别是什么 | 伊人网中文字幕| 日韩中文字幕精品视频| 日本a人精品| 国产又黄又爽免费视频| 国产一区二区不卡在线| 玖玖爱这里只有精品| 日韩欧美国产高清| 51漫画成人app入口| 国产专区一区二区| 欧美亚洲视频| 东方伊人免费在线观看| 69av一区二区三区| 污污的视频在线观看| 国产在线精品一区| 视频在线观看一区| 懂色av蜜臀av粉嫩av永久| 9191成人精品久久| 免费在线观看av电影| 久久精品国产一区二区三区不卡| 久久久蜜桃一区二区人| youjizz亚洲女人| 日韩一区二区三区三四区视频在线观看 | 丁香色欲久久久久久综合网| 不卡一区二区三区四区| 欧美激情黑白配| 色噜噜亚洲精品中文字幕| 免费观看亚洲天堂| 精品国产免费av| 国产精品免费看片| 性猛交xxxx乱大交孕妇印度| 国内精久久久久久久久久人| 国产亚洲电影| 色黄视频免费看| 一本色道亚洲精品aⅴ| 在线看的av网站| 国产成人免费观看| 日韩高清在线一区| 欧美日韩在线观看免费| 日韩精品一区二区视频| 宅男噜噜噜66国产精品免费| 婷婷五月综合缴情在线视频| 欧美国产国产综合| 免费av网站观看| 国产精品专区h在线观看| 精品白丝av| 亚洲欧洲综合网| 亚洲国产婷婷香蕉久久久久久| 国产乱子精品一区二区在线观看| 黄色特一级视频| 亚洲国产精品t66y| 神马午夜精品95| 91精品视频免费观看| 久久高清国产| 国产一级片久久| 最近2019中文免费高清视频观看www99 |