java導(dǎo)出excel最佳實(shí)踐,java大文件excel避免OOM(內(nèi)存溢出)_第1頁(yè)
java導(dǎo)出excel最佳實(shí)踐,java大文件excel避免OOM(內(nèi)存溢出)_第2頁(yè)
java導(dǎo)出excel最佳實(shí)踐,java大文件excel避免OOM(內(nèi)存溢出)_第3頁(yè)
java導(dǎo)出excel最佳實(shí)踐,java大文件excel避免OOM(內(nèi)存溢出)_第4頁(yè)
java導(dǎo)出excel最佳實(shí)踐,java大文件excel避免OOM(內(nèi)存溢出)_第5頁(yè)
已閱讀5頁(yè),還剩6頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、產(chǎn)品需求產(chǎn)品經(jīng)理需要導(dǎo)出一個(gè)頁(yè)面的所有的信息到EXCEL文件。需求分析對(duì)于 excel 導(dǎo)出,是一個(gè)很常見(jiàn)的需求。 最常見(jiàn)的解決方案就是使用 poi 直接同步導(dǎo)出一個(gè) excel 文件。 客戶體驗(yàn) & 服務(wù)性能? 客戶體驗(yàn) 如果導(dǎo)出的文件比較大,比如幾十萬(wàn)條數(shù)據(jù),同步導(dǎo)出頁(yè)面就會(huì)卡主,用戶無(wú)法進(jìn) 行其他操作。? 服務(wù)性能導(dǎo)出的時(shí)候,任務(wù)比較耗時(shí)就會(huì)阻塞主線程。 如果導(dǎo)出的服務(wù)是暴露給外部(前后端分離),這種大量的數(shù)據(jù)傳輸十分消耗性能。 解決方案使用異常處理導(dǎo)出請(qǐng)求,后臺(tái) MQ 通知自己進(jìn)行處理。MQ 消費(fèi)之后,多線程處理 excel 文件導(dǎo)出,生成文件后上傳到 FTP 等文件服務(wù)器。

2、前端直接查詢并且展現(xiàn)對(duì)應(yīng)的任務(wù)執(zhí)行列表,去 FTP 等文件服務(wù)器下載文件即可。EXCELS出需要考慮的問(wèn)題OOM正常的 poi 在處理比較大的 excel 的時(shí)候,會(huì)出現(xiàn)內(nèi)存溢出。 網(wǎng)上的解決方案也比較多。比如官方的SXSSF (Sinee POI 3.8 beta3解決方式?;蛘呤褂梅庋b好的包1. easypoi ExeelBatehExportServer2. hutool BigExeelWriter原理都是 強(qiáng)制使用 xssf 版本的 Excel你也可以使用easyexcel,當(dāng)然這個(gè)注釋文檔有些欠缺,而且設(shè)計(jì)的比較復(fù)雜,不 是很推薦。我這里使用的是 hutool BigExcelWr

3、iter , 懶得自己再寫一遍。FULL GC如果一次查詢 100W 條數(shù)據(jù)庫(kù),然后把這些信息全部加載到內(nèi)存中,是不可取的。 建議有 2 個(gè):1. 限制每一次分頁(yè)的數(shù)量。比如一次最多查詢 1w 條。分成 100 次查詢。(必須)2. 限制查詢得總條數(shù)。比如限制為最多 10W 條。(根據(jù)實(shí)際情況選擇) 雖然使用者提出要導(dǎo)出類似于 3 個(gè)月的所有信息,但是數(shù)量太多,毫無(wú)意義。 (提 出者自己可能體會(huì)不到 )盡量避免FULL-GC的情況發(fā)生,因?yàn)槟壳暗乃蟹绞綄?duì)于 excel的輸出流都會(huì)占用 內(nèi)存, 100W 條很容易導(dǎo)致 FULL-GC。數(shù)據(jù)庫(kù)的壓力 去數(shù)據(jù)庫(kù)讀取的時(shí)候一定要記得分頁(yè),免得給數(shù)據(jù)庫(kù)

4、太大的壓力。 一次讀取太多,也會(huì)導(dǎo)致內(nèi)存直線上升。比如 100W 條數(shù)據(jù),則分成 100 次去數(shù)據(jù)庫(kù)讀取。網(wǎng)絡(luò)傳輸傳統(tǒng)的 excel 導(dǎo)出,都是前端一個(gè)請(qǐng)求,直接 HTTP 同步返回。導(dǎo)出 100W 條,就 在那里傻等。這客戶體驗(yàn)不友好,而且網(wǎng)絡(luò)傳輸,系統(tǒng)占用多種問(wèn)題。 建議使用異步處理的方式,將文件上傳到文件服務(wù)器。前端直接去文件服務(wù)器讀取。 編程的便利性對(duì)于上面提到的工具,比如 Hutool,在表頭的處理方面沒(méi)法很方便的統(tǒng)一。你可以自己定義類似于 easypoi/easyexcel 中的注解,自己反射解析。 然后統(tǒng)一處理表頭即可。lExcel方便優(yōu)雅的excel框架特性?00的方式操作ex

5、cel,編程更加方便優(yōu)雅。?sax模式讀取,SXSS模式寫入。避免excel大文件00M。? 基于注解,編程更加靈活。?寫入可以基于對(duì)象列表,也可以基于 Map,實(shí)際使用更加方便。? 設(shè)計(jì)簡(jiǎn)單,注釋完整。方便大家學(xué)習(xí)改造。 后期特性? 讀取跳過(guò)空白行? excel 樣式相關(guān)的注解開(kāi)發(fā)創(chuàng)作緣由實(shí)際工作和學(xué)習(xí)中, apache poi 操作 excel 過(guò)于復(fù)雜。 近期也看了一些其他的工具框架:? easypoi? easyexcel? hutool-poi都或多或少難以滿足自己的實(shí)際需要,于是就自己寫了一個(gè)操作 excel 導(dǎo)出的工具快速開(kāi)始 引入 Jar 使用 maven 管理。<dep

6、endency><groupId> com.github.houbb </groupId><artifactId> iexcel </artifactId><version> 0.0.2 </version></dependency>說(shuō)明2003版本的excel2007版本的excelSXSSFExcelWriterExcelUtil.getBigExcelWriter()大文件excel,避免OOM定義對(duì)象你可以直接參考ExcelUtilTest.java定義一個(gè)需要寫入/讀取的excel對(duì)象? Exc

7、elFieldModel.java只有聲明了 ExcelField的屬性才會(huì)被處理,使用說(shuō)明:ExcelFieldpublic class ExcelFieldModel ExcelFieldprivate Str ing n ame;ExcelField (headName ="年齡”)private Str ing age;ExcelField (mapKey = "EMAIL" , writeRequire = false , readRequire = alse )privateStri ng email;ExcelField (mapKey = &quo

8、t;ADDRESS", headName ="地址 ”,writeRequire = true )privateStri ng address;/getter and setter寫入例子lExcelWriter的實(shí)現(xiàn)IExcelWriter有幾個(gè)實(shí)現(xiàn)類,你可以直接 new或者借助ExcelUtil 類去創(chuàng)建。lExcelWriter實(shí)現(xiàn)類 ExcelUtil如何創(chuàng)建HSSFExcelWriter ExcelUtil.getO3ExcelWriter()XSSFExcelWriterExcelUtil.getO7ExcelWriter()IExcelWriter 接口說(shuō)明

9、寫入到2003? excelWriter03Test()一個(gè)將對(duì)象列表寫入2003 excel文件的例子。* 寫入到 03 excel 文件*/Test public void excelWriter03Test () / 待生成的 excel 文件路徑final String filePath = "excelWriter03.xls"/ 對(duì)象列表buildModelList ();List<ExcelFieldModel> models =try (IExcelWriter excelWriter = ExcelUtil. get03ExcelWriter

10、(); OutputStream outputStream =new FileOutputStream(filePath) / 可根據(jù)實(shí)際需要,多次寫入列表 excelWriter. write (models);/ 將列表內(nèi)容真正的輸出到 excel 文件 excelWriter. flush (outputStream); catch (IOException e) throw new ExcelRuntimeException (e);? buildModelList()* 構(gòu)建測(cè)試的對(duì)象列表* return 對(duì)象列表 */buildModelList () new ArrayList&

11、lt;>();new ExcelFieldModel ();private List<ExcelFieldModel> List<ExcelFieldModel> models = ExcelFieldModel model =model. setName (" 測(cè)試 1 號(hào) ");model. setAge ( "25" );model. setEmail ( "123" ); model. setAddress (" 貝克街 23 號(hào)");ExcelFieldModel model

12、Two = new ExcelFieldModel (); modelTwo.setName ( " 測(cè)試 2 號(hào)");modelTwo. setAge ( "30" );modelTwo. setEmail ( "125" );modelTwo. setAddress ( " 貝克街 26 號(hào)");models.add (model);models.add (modelTwo);return models;ExcelReaderExcelUtil.getExcelReader()小文件的excel讀取實(shí)現(xiàn)SaxO

13、3ExcelReaderExcelUtil.getBigExcelReader()大文件的2003 excel讀取實(shí)現(xiàn)Sax07ExcelReaderExcelUtil.getBigExcelReader()大文件的2007 excel讀取實(shí)現(xiàn)一次性寫入到2007 excel有時(shí)候列表只寫入一次很常見(jiàn),所有就簡(jiǎn)單的封裝了下:*只寫入一次列表*其實(shí)是對(duì)原來(lái)方法的簡(jiǎn)單封裝*/Testpublic void on ceWriterA ndFlushO7Test () II待生成的excel文件路徑finalStri ng filePath ="on ceWriterA ndFlushO7.

14、xlsx"/對(duì)象列表List<ExcelFieldModel> models =buildModelList ();/對(duì)應(yīng)的excel寫入對(duì)象IExcelWriter excelWriter = ExcelUtil.getO7ExcelWriter ();/只寫入一次列表ExcelUtil.on ceWriteA ndFlush(excelWriter, models, filePath);讀取例子excel讀取時(shí)會(huì)根據(jù)文件名稱判斷是哪個(gè)版本的exceLlExcelReade 的實(shí)現(xiàn)IExcelReader有幾個(gè)實(shí)現(xiàn)類,你可以直接 new或者借助ExcelUtil 類去創(chuàng)

15、建IExcelReader 實(shí)現(xiàn)說(shuō)明類ExcelUtil如何創(chuàng)建IExcelReader 接口說(shuō)明 excel讀取的例子/*讀取測(cè)試*/Testpublic void readWriterTest () File file =new File( "excelWriterO3.xls" );IExcelReader<ExcelFieldModel> excelReader = ExcelUtil.getExcelReader (file);List<ExcelFieldModel> models = excelReader.readAll (Excel

16、FieldModel.class );System. out . println (models);ExcelField注解說(shuō)明ExcelField 的屬性說(shuō)明如下:默認(rèn)屬性類型 值 說(shuō)明mapKeyStri ngIlliheadNameStri ngIlli僅用于生成的入?yún)閙ap時(shí),會(huì)將map.key對(duì)應(yīng)的 值映射到bean上。如果不傳:默認(rèn)使用當(dāng)前字段 名稱excel表頭字段名稱,如果不傳:默認(rèn)使用當(dāng)前字 段名稱writeRequire boolea n true readRequire boolea n trueexcel文件是否需要寫入此字段excel文件是否讀取此字段*lExcel

17、Writer 接口說(shuō)明寫出數(shù)據(jù),本方法只是將數(shù)據(jù)寫入Workbook中的Sheet,并不寫出到文件<br><p>data中元素支持的類型有:<pre>1. Bean,既元素為一個(gè) Bean,第一個(gè)Bean的字段名列表會(huì)作為首行,剩下的行為Bean的字段值列表,data表示多行<br>* </pre>* param data 數(shù)據(jù)* return this*/IExcelWriter write (Collectionv?> data);寫出數(shù)據(jù),本方法只是將數(shù)據(jù)寫入Workbook中的Sheet,并不寫出到文件<br>

18、;將map按照targetClass轉(zhuǎn)換為對(duì)象列表應(yīng)用場(chǎng)景:直接mybatis mapper查詢出的map結(jié)果,或者其他的構(gòu)造結(jié)果。param mapList map 集合param targetClass目標(biāo)類型return this*/final ClassIExcelWriter write (Collection<Map<String, Object>> mapList, <?> targetClass);/*將 Excel Workbook 刷出到輸出流*param outputStream 輸出流 return this*/IExcelWriter flush (OutputStream outputStream);指定 sheet創(chuàng)建 IExcelWriter 的

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論