欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java?Export大量數(shù)據(jù)導(dǎo)出和打包

 更新時間:2023年06月20日 14:51:30   作者:我是一顆小虎牙_  
這篇文章主要為大家介紹了java?Export大量數(shù)據(jù)的導(dǎo)出和打包實(shí)現(xiàn)過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

項(xiàng)目需求

導(dǎo)出生成大批量數(shù)據(jù)的文件,一個Excel中最多存有五十萬條數(shù)據(jù),查詢多余五十萬的數(shù)據(jù)寫多個Excel中。導(dǎo)出完成是生成的多個Excel文件打包壓縮成zip,而后更新導(dǎo)出記錄中的壓縮文件路徑。

大數(shù)據(jù)量文件一般采用異步生成文件,導(dǎo)出時首先授權(quán)生成一個流水號,而后將數(shù)據(jù)攜帶流水號請求導(dǎo)出接口。

拋開實(shí)際業(yè)務(wù),做成一個比較公共的導(dǎo)出功能。

參數(shù)說明

{
    "className": "ValideData",         //導(dǎo)出的數(shù)據(jù)的實(shí)體類,類中有別名和順序相關(guān)的注解
    "createUser": "",               //操作人
    "downLoadNo": "202203181504732568468066304",    //下載流水號
    "fileName": "機(jī)卡綁定",          //文件名      fileName+HHmmssSSS.xlsx
    "keys": [                       //redis key的數(shù)據(jù),分批獲取數(shù)據(jù)
    ],
    "remark": "機(jī)卡綁定",               //備注(不關(guān)注)
    "type": "機(jī)卡綁定"                  //導(dǎo)出類型(不關(guān)注)
}

坐標(biāo)

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-compress</artifactId>
  <version>1.21</version>
</dependency>

注:拋開導(dǎo)出前的參數(shù)校驗(yàn),只關(guān)注導(dǎo)出操作 。

主要代碼

邏輯說明:

  • 導(dǎo)出前將請求參數(shù)更新到導(dǎo)出記錄中。
  • 類加載器加載需要導(dǎo)出數(shù)據(jù)的實(shí)體類
  • 設(shè)置一個數(shù)據(jù)量指針,記錄到每個文件的數(shù)據(jù)量
  • 達(dá)到閾值時指定文件寫出到磁盤并清緩。
  • 重置數(shù)據(jù)量指針,新增一條文件記錄(循環(huán))
  • 數(shù)據(jù)量指針未到閾值時但數(shù)據(jù)已經(jīng)查詢完成---->>寫入剩余數(shù)據(jù)
  • 查詢該流水號的所有文件記錄
  • 壓縮文件并返回壓縮文件地址
  • 更新到導(dǎo)出記錄中

主流程

public void bigDataExport(PortDto dto) throws Exception {
    long start = System.currentTimeMillis();
    log.info("開始導(dǎo)出,批次號:<{}>, 開始時間:{}", dto.getDownLoadNo(), DateUtil.now());
    //修改導(dǎo)出記錄
    LambdaUpdateWrapper<PortDto> updateWrapper = new LambdaUpdateWrapper<>();
    updateWrapper.eq(PortDto::getDownLoadNo, dto.getDownLoadNo());
    //生成導(dǎo)出記錄
    int row = this.baseMapper.update(dto, updateWrapper);
    if (row > 0) {
        log.info("批次號:<{}>準(zhǔn)備生成文件", dto.getDownLoadNo());
        try {
            Iterator<String> iterator = keys.iterator();
            Workbook workbook = null;
            ExportParams params = new ExportParams();
            //加載導(dǎo)出數(shù)據(jù)實(shí)體類
            Class<?> aClass = Class.forName(entityBasePackage + dto.getClassName());
            int element = 0;
            while (iterator.hasNext()) {
                String key = iterator.next();
                Collection<?> list = getList(key, aClass);
                element += list.size();
                workbook = ExcelExportUtil.exportBigExcel(params, aClass, list);
                //文件數(shù)據(jù)達(dá)到閾值
                if (element >= maxDataCount) {
                    String fileName = dto.getFileName() + "_" + DateUtil.format(new Date(),
                            "HHmmssSSS") + ".xlsx";
                    ExcelExportUtil.closeExportBigExcel();
                    FileOutputStream fos =
                            new FileOutputStream(fileProp.getPath().getPath() + fileName);
                    workbook.write(fos);
                    fos.close();
                    element = 0;
                    //更新地址
                    Map<String, Object> map = new HashMap<>();
                    map.put("downloadNo", dto.getDownLoadNo());
                    map.put("filePath", fileProp.getPath().getPath() + fileName);
                    map.put("createTime", new Date());
                    this.baseMapper.insertPathRecord(map);
                    log.info("文件寫入完成,文件名:{}", fileName);
                    continue;
                }
                iterator.remove();
            }
            //寫入剩余文件
            if (element != 0) {
                String fileName = dto.getFileName() + "_" + DateUtil.format(new Date(),
                        "HHmmssSSS") + ".xlsx";
                ExcelExportUtil.closeExportBigExcel();
                FileOutputStream fos = new FileOutputStream(fileProp.getPath().getPath() + fileName);
                workbook.write(fos);
                fos.close();
                element = 0;
                //更新地址
                Map<String, Object> map = new HashMap<>();
                map.put("downloadNo", dto.getDownLoadNo());
                map.put("filePath", fileProp.getPath().getPath() + fileName);
                map.put("createTime", new Date());
                this.baseMapper.insertPathRecord(map);
                log.info("文件寫入完成,文件名:{}", fileName);
            }
            long end = System.currentTimeMillis();
            log.info("導(dǎo)出結(jié)束,批次號:<{}>, 結(jié)束時間:{}, 耗時:{}", dto.getDownLoadNo(), DateTime.of(end),
                    DateUtil.formatBetween(end - start));
        } catch (Exception e) {
            log.info("批次號<{}>導(dǎo)出異常:", dto.getDownLoadNo(), e);
            throw new BusinessException("");
        } finally {
            log.info("批次號<{}>生成文件結(jié)束,準(zhǔn)備壓縮文件,修改狀態(tài)", dto.getDownLoadNo());
            //合并文件到導(dǎo)出文件記錄主表
            //當(dāng)只有一個文件記錄時直接更新主表文件地址
            List<PortDto> recordList = exportDao.getPathRecord(dto);
            if (recordList.size() > 1) {
                //zipPath
                dto.setFilePath(zcat(dto, recordList));
            } else {
                //xlsxPath
                dto.setFilePath(recordList.size()==0? "":recordList.get(0).getFilePath());
            }
            updateWrapper.clear();
            updateWrapper.set(PortDto::getFilePath, dto.getFilePath());
            updateWrapper.set(PortDto::getSuccessTime, new Date());
            updateWrapper.set(PortDto::getStatus, "1");
            updateWrapper.eq(PortDto::getDownLoadNo, dto.getDownLoadNo());
            this.baseMapper.update(null, updateWrapper);
            log.info("批次號<{}>更新下載記錄表文件地址,修改狀態(tài)成功", dto.getDownLoadNo());
        }
    }
}

文件壓縮

/**
 *  多文件壓縮
 * @param dto 導(dǎo)出信息
 * @Param recordList 文件路徑
 * @return void
 * @throws
 * @author Surpass
 * @date 2022/3/17 9:59
 */
private String zcat(PortDto dto, List<PortDto> recordList) throws Exception {
    String fileName = dto.getFileName() + "_" + DateUtil.format(new Date(), "HHmmssSSS") + ".zip";
    String zipPath = fileProp.getPath().getPath() + fileName;
    Archiver archiver = CompressUtil.createArchiver(
            CharsetUtil.CHARSET_UTF_8,
            ArchiveStreamFactory.ZIP,
            new File(zipPath)
    );
    for (PortDto portDto : recordList) {
        archiver.add(FileUtil.file(portDto.getFilePath()));
    }
    archiver.finish();
    archiver.close();
    return zipPath;
}

查詢數(shù)據(jù)

/**
 *   查詢redis數(shù)據(jù)
 * @param key
 * @param cls
 * @return java.util.Collection<?>
 * @throws
 * @author Surpass
 * @date 2022/3/18 15:51
 */
private Collection<?> getList(String key, Class<?> cls) {
    List<String> list = redis.getList(key);
    return list.stream().map(item -> JSONObject.parseObject(item, cls)).collect(Collectors.toList());
}

補(bǔ)充

導(dǎo)出還設(shè)置了隊(duì)列計(jì)數(shù)器來限制同一時間最大的導(dǎo)出請求,使用aop在申請流水號時計(jì)數(shù)器+1,導(dǎo)出完成或者異常時隊(duì)列計(jì)數(shù)器-1。導(dǎo)出完成后根據(jù)操作人發(fā)送郵件通知導(dǎo)出結(jié)果。

以上就是java Export大量數(shù)據(jù)導(dǎo)出和打包的詳細(xì)內(nèi)容,更多關(guān)于java Export數(shù)據(jù)導(dǎo)出打包的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java 中引入內(nèi)部類的意義?

    Java 中引入內(nèi)部類的意義?

    這篇文章主要介紹了Java 中引入內(nèi)部類的意義?文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,,需要的朋友可以參考下
    2019-06-06
  • SpringBoot基于AbstractRoutingDataSource實(shí)現(xiàn)多數(shù)據(jù)源動態(tài)切換

    SpringBoot基于AbstractRoutingDataSource實(shí)現(xiàn)多數(shù)據(jù)源動態(tài)切換

    本文主要介紹了SpringBoot基于AbstractRoutingDataSource實(shí)現(xiàn)多數(shù)據(jù)源動態(tài)切換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Spring?Boot實(shí)現(xiàn)分布式系統(tǒng)中的服務(wù)發(fā)現(xiàn)和注冊(最新推薦)

    Spring?Boot實(shí)現(xiàn)分布式系統(tǒng)中的服務(wù)發(fā)現(xiàn)和注冊(最新推薦)

    在本文中,我們深入探討了Spring?Boot如何實(shí)現(xiàn)分布式系統(tǒng)中的服務(wù)發(fā)現(xiàn)和注冊,我們使用Eureka作為服務(wù)注冊中心,Ribbon作為負(fù)載均衡器,Hystrix作為熔斷器,成功地實(shí)現(xiàn)了服務(wù)發(fā)現(xiàn)、服務(wù)注冊、負(fù)載均衡和服務(wù)熔斷等功能,需要的朋友參考下吧
    2023-06-06
  • Springboot并發(fā)調(diào)優(yōu)之大事務(wù)和長連接

    Springboot并發(fā)調(diào)優(yōu)之大事務(wù)和長連接

    這篇文章主要介紹了Springboot并發(fā)調(diào)優(yōu)之大事務(wù)和長連接,重點(diǎn)分享長事務(wù)以及長連接導(dǎo)致的并發(fā)排查和優(yōu)化思路和示例,具有一定的參考價值,感興趣的可以了解一下
    2022-05-05
  • Java Swing JSlider滑塊的實(shí)現(xiàn)示例

    Java Swing JSlider滑塊的實(shí)現(xiàn)示例

    這篇文章主要介紹了Java Swing JSlider滑塊的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • 詳解SpringBoot上傳圖片到阿里云的OSS對象存儲中

    詳解SpringBoot上傳圖片到阿里云的OSS對象存儲中

    這篇文章主要介紹了SpringBoot上傳圖片到阿里云的OSS對象存儲中,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • 一文講通Java為什么不支持多繼承原理

    一文講通Java為什么不支持多繼承原理

    這篇文章主要為大家介紹了java為什么不支持多繼承原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Java查找不重復(fù)無序數(shù)組中是否存在兩個數(shù)字的和為某個值

    Java查找不重復(fù)無序數(shù)組中是否存在兩個數(shù)字的和為某個值

    今天小編就為大家分享一篇關(guān)于Java查找不重復(fù)無序數(shù)組中是否存在兩個數(shù)字的和為某個值,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • 如何使用攔截器獲取請求的入?yún)⒉⑵滢D(zhuǎn)化為Java對象詳解

    如何使用攔截器獲取請求的入?yún)⒉⑵滢D(zhuǎn)化為Java對象詳解

    這篇文章主要介紹了如何使用攔截器獲取請求的入?yún)⒉⑵滢D(zhuǎn)化為Java對象的相關(guān)資料,文中介紹了兩種實(shí)現(xiàn)的方法,并給出了詳細(xì)的代碼示例,需要的朋友可以參考下
    2025-02-02
  • Java實(shí)現(xiàn)布隆過濾器的幾種方式總結(jié)

    Java實(shí)現(xiàn)布隆過濾器的幾種方式總結(jié)

    這篇文章給大家總結(jié)了幾種Java實(shí)現(xiàn)布隆過濾器的方式,手動硬編碼實(shí)現(xiàn),引入Guava實(shí)現(xiàn),引入hutool實(shí)現(xiàn),通過redis實(shí)現(xiàn)等幾種方式,文中有詳細(xì)的代碼和圖解,需要的朋友可以參考下
    2023-07-07

最新評論