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

java學(xué)習(xí)之JasperReport踩坑

 更新時(shí)間:2018年01月20日 11:53:26   作者:老爺爺  
本篇文章介紹的是在JAVA學(xué)習(xí)中JasperReport遇到的坑以及解決辦法,有需要的朋友參考下吧。

下面進(jìn)入正題,來(lái)介紹下今天的豬腳JasperReport或者叫它ireport亦或jasperstudio,當(dāng)然后面兩個(gè)是它的可視化工具。

JasperReport是個(gè)什么東西?

這貨其實(shí)在國(guó)內(nèi)用戶也不少,是個(gè)國(guó)外的產(chǎn)品,而且可以說(shuō)在JAVA報(bào)表領(lǐng)域應(yīng)用是相當(dāng)?shù)膹V泛。

我當(dāng)初剛剛接觸這個(gè)報(bào)表的時(shí)候還是相當(dāng)?shù)南矚g的,最主要的是它的可視化工具,真的是讓我欲罷不能,竟然可以通過(guò)簡(jiǎn)單畫圖的方式來(lái)設(shè)計(jì)JAVA報(bào)表。說(shuō)起畫圖就是可以通過(guò)可視化的工具,讓我們可視化的設(shè)計(jì)報(bào)表模板,并且它支持輸出的文件格式很廣泛,包括EXCEL、WORD、PDF、HTML、XML、CSV等等。

看起來(lái)是不是很強(qiáng)大,一次設(shè)計(jì),多次復(fù)用。當(dāng)然強(qiáng)大得的東西,往往都有兩面性,這不就被我遇到了,折磨了我相當(dāng)長(zhǎng)的時(shí)間,后文會(huì)詳細(xì)描述的。

JasperReport的大胸弟

前面我說(shuō),JasperReport或者叫它ireport或jasperstudio,其實(shí)這是不準(zhǔn)確的。二弟ireport、三弟jasperstudio其實(shí)是jasper的輔助視覺設(shè)計(jì)工具,你不用它也能設(shè)計(jì)jasper報(bào)表,多寫點(diǎn)XML白。5.5之前這個(gè)工具叫ireport,5.5之后隨著三弟jasperstudio的出生,ireport就被完全替代了,其實(shí)這兩個(gè)工具基本上是一樣的,一奶同胞。

具體的工作流程:

①首先Jasper會(huì)獲取需要輸出的格式信息的xml文件,然后從xml文件中編譯出.jasper類型的文件,然后這個(gè)jasper文件可以在我們的應(yīng)用程序中被加載生成最終的報(bào)表。有沒(méi)有很熟悉的感覺,是的,這一點(diǎn)和java很像,都需要編譯一下。

下圖,就是ireport的操作界面,jasperstudio類似,就不貼了,大家可以自行百度下。

上圖每種類型的band簡(jiǎn)單介紹一下。

(1)Title band:title段只在整個(gè)報(bào)表的第一頁(yè)的最上面部分顯示,除了第一頁(yè)以外,不管報(bào)表中共有多少個(gè)頁(yè)面也不會(huì)再出現(xiàn)Title band中的內(nèi)容。

(2)pageHeader Band:顧名思義,pageHeader 段中的內(nèi)容將會(huì)在整個(gè)報(bào)表中的每一個(gè)頁(yè)面中都會(huì)出現(xiàn),顯示在位置在頁(yè)面的上部,如果是報(bào)表的第一頁(yè),pageHeader 中的內(nèi)容將顯示在Title Band下面,除了第一頁(yè)以外的其他所有頁(yè)面中pageHeader中的內(nèi)容將在顯示在頁(yè)面的最上端。

(3)pageFooter Band:顯示在所在頁(yè)面的最下端。

(4)lastPageFooter Band:顯示在最后一頁(yè)的最下端。

(5)Detail Band:報(bào)表內(nèi)容段,在這個(gè)Band 中設(shè)計(jì)報(bào)表中需要重復(fù)出現(xiàn)的內(nèi)容,Detail 段中的內(nèi)容每頁(yè)都會(huì)出現(xiàn)。

(6)columnHeader Band:針對(duì)Detail Band的表頭段,一般情況下在這個(gè)段中畫報(bào)表的表頭。

(7)columnFooter Band:針對(duì)Detail Band的表尾段。

(8)Summary Band:表格的合計(jì)段,出現(xiàn)在整個(gè)報(bào)表的最后一頁(yè)中的Detail band 的后面,一般用來(lái)統(tǒng)計(jì)報(bào)表中某一個(gè)或某幾個(gè)字段的合計(jì)值。

上面就是可視化的工具的全部,其實(shí)怎么用很簡(jiǎn)單,上手摸索下就會(huì)了,既然是踩坑實(shí)錄,這個(gè)自然不是重點(diǎn),不說(shuō)了。

代碼中的應(yīng)用

這是我總結(jié)的步驟,可能描述的不是很準(zhǔn)確,大家湊合下

①設(shè)計(jì)模板,生成JRXML文件,↑↑上面的可視化工具設(shè)計(jì)你所需要的模板樣式

②編譯模板,JRXML編譯成Jasper文件,就像java中的.java和.class文件一樣,程序中運(yùn)行的需要是*.jasper的二進(jìn)制文件。

其實(shí)這一步可以直接用ireport編譯生成.jasper,當(dāng)然也可以在運(yùn)行時(shí)通過(guò)jasper程序編譯。但是建議如果在程序中編譯的話,jasper版本最好和ireport或者jasperstudio的版本一致。

③執(zhí)行報(bào)表(數(shù)據(jù)填充到報(bào)表)

1、 加載模板生成Jasperreport對(duì)象

2、利用JasperFillManager,生成JasperPrint對(duì)象

④最后利用JRXlsxExporter導(dǎo)出類,將報(bào)表導(dǎo)出或者展示

加載模板

既然我們已經(jīng)利用可視化工具生成了.jasper或者.jrxml文件了,自然是需要讓程序加載它。

加載的代碼,返回jasperport對(duì)象

    if (urlPath.endsWith(".jrxml")) {
      //compile jrxml to jasper
      try {
        InputStream is = url.openStream();
        jasperReport = JasperCompileManager.compileReport(is);
      } catch (IOException e) {
        throw new BaseException("Load jasper error", e);
      } catch (JRException e) {
        throw new BaseException("The jrxml template transform to jasper file error", e);
      } catch (Throwable e) {
        log.error(e);
        throw new BaseException(e.getMessage());
      }
    } else if (urlPath.endsWith(".jasper")) {
      try {
        InputStream is = url.openStream();
        jasperReport = (JasperReport) JRLoader.loadObject(is);
      } catch (IOException e) {
        throw new BaseException("Load jasper error", e);
      } catch (JRException e) {
        throw new BaseException("The jrxml template file error", e);
      } catch (Throwable e) {
        log.error(e);
        throw new BaseException(e.getMessage());
      }
    } else {
      throw new BaseException("Invalid file!");
    }

獲取報(bào)表中的數(shù)據(jù)源

這里我采用javabean的方式獲取

      JRDataSource dataSource = null;
      if (fieldValues != null && fieldValues.size() > 0) {
        dataSource = new JRBeanCollectionDataSource(fieldValues);
      } else {
        dataSource = new JREmptyDataSource();
      }

fieldValues 為數(shù)據(jù)庫(kù)中獲取的pojo集合。

執(zhí)行報(bào)表填充

得到j(luò)asperprint對(duì)象

Map<String, Object> parameterValue = new HashMap<String, Object>();
jasperPrint = JasperFillManager.fillReport(jasperReport, parameterValue, dataSource);

最后我們利用JRXlsxExporter導(dǎo)出報(bào)表

這個(gè)也是需要配置參數(shù)最多的一個(gè)地方

baos = new ByteArrayOutputStream();
exporter = new JRXlsxExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, baos);
exporter.exportReport();

完成,數(shù)據(jù)已經(jīng)寫入輸出流中了,怎么輸出自己決定,是不是比其他方式代碼簡(jiǎn)介很多。

確實(shí)在代碼書寫中JasperReport有著無(wú)法比擬的優(yōu)勢(shì),各種api已經(jīng)封裝好。但是可能是恰恰做的太多,問(wèn)題也不少。

JasperReport的問(wèn)題

1、兩行前的空白

如果你使用上面的代碼導(dǎo)出EXCEL的話,你會(huì)發(fā)現(xiàn)Excel的背景是白色,沒(méi)了Excel一個(gè)個(gè)的小格子,這是因?yàn)閖asper默認(rèn)背景為白色,這樣在導(dǎo)出其他格式時(shí)也好做到兼容,當(dāng)然當(dāng)我們導(dǎo)出EXCEL并不需要。只需要加上下面兩行就可以解決。

      //去除兩行之前的空白 
      exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,Boolean.TRUE); 
      exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_COLUMNS,Boolean.TRUE); 
      //設(shè)置Excel表格的背景顏色為默認(rèn)的白色 
      exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND,Boolean.FALSE);

2、數(shù)據(jù)量很大,title多次寫入

如果你一個(gè)Sheet數(shù)據(jù)很多,可能會(huì)遇到表頭多次打印的情況,這種情況下,你需要加上高度設(shè)置。

Field pageHeight = JRBaseReport.class.getDeclaredField(
          "pageHeight");
      pageHeight.setAccessible(true);
      pageHeight.setInt(jasperReport, Integer.MAX_VALUE);

3、Cell的類型的問(wèn)題

有時(shí)候我們導(dǎo)出的Excel報(bào)表,需要使用Excel的函數(shù)計(jì)算,如果全都是文本格式,自然計(jì)算不了,這種情況下,我們需要使用

 //自動(dòng)選擇格式
 exporter.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);

切記,在報(bào)表設(shè)計(jì)時(shí),F(xiàn)ield字段選擇正確的類型。

4、多Sheet的問(wèn)題

我上面那個(gè)簡(jiǎn)單的例子,只是一個(gè)文件中包含一個(gè)Sheet頁(yè),假如我們的需求是一個(gè)文件導(dǎo)出多個(gè)Sheet怎么辦,別急,這個(gè)Japser早已為我們想到了。

只需要將上文中導(dǎo)出步驟換成下面這個(gè)樣子

baos = new ByteArrayOutputStream();
exporter = new JRXlsxExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT_LIST, listJasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, baos);
//設(shè)置為true,即可在一個(gè)excel中,每個(gè)單獨(dú)的jasper對(duì)象放入到一個(gè)sheet頁(yè)中
exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET,Boolean.TRUE);

JRExporterParameter.JASPER_PRINT_LIST,傳入一個(gè)listJasperPrint的集合,每個(gè)JasperPrint即一個(gè)Sheet頁(yè)。

5、Linux下啟動(dòng)不報(bào)錯(cuò),但是無(wú)法導(dǎo)出報(bào)表

其實(shí)這個(gè)問(wèn)題也困擾了我很久,后來(lái)在大佬的幫助下才想起來(lái)問(wèn)題所在,因?yàn)樗鼟伋龅母静皇莻€(gè)Exception,而是Error。我看到網(wǎng)上也有同學(xué)問(wèn)這個(gè)問(wèn)題,所以貼出來(lái)。

可以用throwable捕獲,就可以得到錯(cuò)誤信息,報(bào)錯(cuò):java.lang.InternalError: Can't connect to X11 window server using ':0.0' as

解決方法:修改tomcat/bin/catalina.sh 加JAVA_OPTS="$JAVA_OPTS  -Djava.awt.headless=true"

6、大數(shù)據(jù)內(nèi)存溢出和內(nèi)存泄露問(wèn)題?。?/p>

這里需要說(shuō)一下,EXCEL 03和07版的區(qū)別,03版我記得好像是只支持65532行吧,而07版之后就大的多了,具體數(shù)字我忘了,反正不是一個(gè)數(shù)量級(jí)的。

JRXlsxExporter支持導(dǎo)出xlsx文件,

JRXlsExporter則是xls的文件,很好辨認(rèn),導(dǎo)出的工具和excel的格式一樣。

然后是內(nèi)存溢出和內(nèi)存泄露問(wèn)題,這個(gè)我相信玩JAVA的朋友基本上都遇到過(guò)。

關(guān)于內(nèi)存溢出最通常的解決辦法便是增大容器的內(nèi)存,增加tomcat的內(nèi)存大小,方法大家可以百度,有很多,不重復(fù)造輪子了。

這里提醒下,如果你使用的是tomcat的話,windows安裝版,解壓縮版和Linux版的配置方式都是不同的,需要注意下。

這里我需要介紹的是JasperReport的方式,其實(shí)JasperReport是對(duì)大數(shù)據(jù)有解決方案的,在很早期的版本便推出了,JRFileVirtualizer的仿真器。

這個(gè)東西是做啥用的呢,其實(shí)它會(huì)根據(jù)你設(shè)置的參數(shù),將數(shù)據(jù)寫到硬盤的臨時(shí)文件上,這樣解決了填充報(bào)表時(shí)內(nèi)存占用過(guò)大溢出的問(wèn)題。

目前JasperReport有3個(gè)仿真器,都是用來(lái)解決這個(gè)問(wèn)題的。

分別是:

①JRFileVirtualizer

②JRSwapFileVirtualizer

③JRGzipVirtualizer

這三個(gè)仿真器又有什么區(qū)別呢?

首先是推出最早的JRFileVirtualizer,我在測(cè)試時(shí),當(dāng)導(dǎo)出30W左右的數(shù)據(jù),就會(huì)報(bào)內(nèi)存溢出,后來(lái)加上這個(gè)后就可以正常導(dǎo)出了。這個(gè)仿真器會(huì)把每一個(gè)對(duì)象生成一個(gè)臨時(shí)文件存放在硬盤上解決內(nèi)存占用的問(wèn)題,但是因?yàn)楫a(chǎn)生的臨時(shí)文件較多,無(wú)形中增加了文件創(chuàng)建和刪除的內(nèi)存消耗,所以并不是很推薦。

//寫多個(gè)文件
 JRFileVirtualizer virtualizer = new JRFileVirtualizer(2, catchPath);
 Map<String, Object> parameterValue = new HashMap<String, Object>();
 parameterValue.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
virtualizer.setReadOnly(true);

catchPath為文件緩存路徑,必須真實(shí)存在,否則會(huì)報(bào)錯(cuò)。

然后是JRSwapFileVirtualizer,這個(gè)是為了解決JRFileVirtualizer的問(wèn)題而推出的。這個(gè)仿真器,只會(huì)創(chuàng)建一個(gè)臨時(shí)文件,每個(gè)對(duì)象會(huì)占這個(gè)文件的一部分,所以就減少的文件創(chuàng)建和刪除的內(nèi)存消耗,其實(shí)這個(gè)也不是特別推薦。

//寫單個(gè)文件
RSwapFile arquivoSwap = new JRSwapFile(catchPath, 4096, 25);
JRAbstractLRUVirtualizer virtualizer = new JRSwapFileVirtualizer(2, arquivoSwap, true);
    
Map<String, Object> parameterValue = new HashMap<String, Object>();
parameterValue.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
virtualizer.setReadOnly(true);

最后是JRGzipVirtualizer這個(gè),看到Gzip,不知道你是否有聯(lián)系到壓縮這個(gè)詞匯。沒(méi)錯(cuò),這個(gè)仿真器就是使用一種特殊的壓縮算法,可以將內(nèi)存占用壓縮到二十分之一還是十分之一來(lái)著,總之很神奇。

JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(2);
Map<String, Object> parameterValue = new HashMap<String, Object>();
parameterValue.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
jasperPrint = JasperFillManager.fillReport(jasperReport, parameterValue, dataSource);

說(shuō)了這么多,總之就是三種仿真器解決內(nèi)存溢出問(wèn)題,我也看了很多博客里面寫利用JRFileVirtualizer,解決內(nèi)存大數(shù)據(jù)問(wèn)題。然后我在這里想說(shuō),我最最最不推薦使用JRFileVirtualizer仿真器,因?yàn)樗粌H創(chuàng)建文件消耗大,還有個(gè)很嚴(yán)重的BUG,內(nèi)存泄露?。?!還有JRSwapFileVirtualizer也有這個(gè)問(wèn)題。

另外,需要說(shuō)明的是不使用仿真器,也會(huì)有內(nèi)存泄露的問(wèn)題,當(dāng)你導(dǎo)出報(bào)表后,dump出堆棧信息,會(huì)發(fā)現(xiàn)net.sf.jasperreports.engine.fill.JRTemplatePrintText類的實(shí)例特別多,無(wú)法回收,無(wú)法回收?。?!并且最新版的japserreport 6.x依舊存在這個(gè)問(wèn)題,在jasper的社區(qū)和Stack Overflow存在很多這樣的問(wèn)題,而沒(méi)有解決方案。

這里推薦JRGzipVirtualizer仿真器,雖然依舊存在泄露問(wèn)題,但是因?yàn)楠?dú)特的壓縮算法,已經(jīng)將內(nèi)存泄露問(wèn)題控制在很小的范圍里了,算是一種緩解的方案吧,大概泄露的內(nèi)存占用緩解了九成以上。

總的來(lái)說(shuō),我現(xiàn)在已經(jīng)放棄這種方案了,寫出來(lái)也是為了后來(lái)的兄弟少走彎路。擼了一個(gè)POI的工具類,接下來(lái)準(zhǔn)備把所有的報(bào)表改成POI導(dǎo)出的方式,話說(shuō)POI的大數(shù)據(jù)方案還是挺不錯(cuò)的。

相關(guān)文章

  • Spring源碼解密之默認(rèn)標(biāo)簽的解析

    Spring源碼解密之默認(rèn)標(biāo)簽的解析

    這篇文章主要給大家介紹了關(guān)于Spring源碼解密之默認(rèn)標(biāo)簽的解析的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • springboot2.x使用Jsoup防XSS攻擊的實(shí)現(xiàn)

    springboot2.x使用Jsoup防XSS攻擊的實(shí)現(xiàn)

    這篇文章主要介紹了springboot2.x使用Jsoup防XSS攻擊的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • Java語(yǔ)言中4種內(nèi)部類的超詳細(xì)講解

    Java語(yǔ)言中4種內(nèi)部類的超詳細(xì)講解

    這篇文章主要給大家介紹了關(guān)于Java語(yǔ)言中4種內(nèi)部類的超詳細(xì)講解,內(nèi)部類可以分為:實(shí)例內(nèi)部類、靜態(tài)內(nèi)部類和成員內(nèi)部類,每種內(nèi)部類都有它特定的一些特點(diǎn),文中介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • java之路徑分隔符介紹

    java之路徑分隔符介紹

    考慮到程序的可移植性,創(chuàng)建文件時(shí)建議大家選用"/",因?yàn)榻?jīng)過(guò)測(cè)試用java創(chuàng)建文件時(shí)在windows平臺(tái)下用“/”也是可以的,java貌似在后臺(tái)作過(guò)處理了。
    2013-03-03
  • 如何利用IDEA搭建SpringBoot項(xiàng)目整合mybatis實(shí)現(xiàn)簡(jiǎn)單的登錄功能

    如何利用IDEA搭建SpringBoot項(xiàng)目整合mybatis實(shí)現(xiàn)簡(jiǎn)單的登錄功能

    這篇文章主要介紹了如何利用IDEA搭建SpringBoot項(xiàng)目整合mybatis實(shí)現(xiàn)簡(jiǎn)單的登錄功能,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Java實(shí)戰(zhàn)之晚會(huì)抽獎(jiǎng)系統(tǒng)的實(shí)現(xiàn)

    Java實(shí)戰(zhàn)之晚會(huì)抽獎(jiǎng)系統(tǒng)的實(shí)現(xiàn)

    這篇文章主要介紹了如何利用Java語(yǔ)言編寫一個(gè)晚會(huì)抽獎(jiǎng)系統(tǒng),文中采用到的技術(shù)有Jdbc、Servlert、JavaScript、JQuery、Ajax等,感興趣的可以學(xué)習(xí)一下
    2022-03-03
  • Intellij無(wú)法創(chuàng)建java文件解決方案

    Intellij無(wú)法創(chuàng)建java文件解決方案

    這篇文章主要介紹了Intellij無(wú)法創(chuàng)建java文件解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • SpringBoot實(shí)現(xiàn)異步消息處理的代碼示例

    SpringBoot實(shí)現(xiàn)異步消息處理的代碼示例

    在現(xiàn)代應(yīng)用程序中,異步消息處理是一項(xiàng)至關(guān)重要的任務(wù)。它可以提高應(yīng)用程序的性能、可伸縮性和可靠性,同時(shí)也可以提供更好的用戶體驗(yàn),本文將介紹如何使用Spring Boot實(shí)現(xiàn)異步消息處理,并提供相應(yīng)的代碼示例
    2023-06-06
  • SpringBoot使用AOP統(tǒng)一日志管理的方法詳解

    SpringBoot使用AOP統(tǒng)一日志管理的方法詳解

    這篇文章主要為大家分享一個(gè)干貨:超簡(jiǎn)潔SpringBoot使用AOP統(tǒng)一日志管理,文中的示例代碼講解詳細(xì),感興趣的小伙伴快跟隨小編一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Java中枚舉的實(shí)現(xiàn)原理介紹

    Java中枚舉的實(shí)現(xiàn)原理介紹

    大家好,本篇文章主要講的是Java中枚舉的實(shí)現(xiàn)原理介紹,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12

最新評(píng)論