這是我學習JasperReport的一點經驗,歡迎大家指正、賜教,我只是起個磚塊的作用,大家就接着拋玉吧,希望最後真的能累成一個必備手冊,呵呵。
假設大家已經對JasperReport有一定的瞭解(至少知道大概的開發流程),這裏就不贅述JasperReport的好處、設計、表達式的定義等JasperReport自帶文檔裏有的東西了。
遇到的問題&我的解決方法:
l Jsp生成不了PDF的問題
l 生成HTML時JRHtmlExporterParameter.IMAGES_MAP的問題
l 中文顯示的問題
l 圖片顯示的實現方法(JFreeChart)
l 我的通用 .jasper 生成方法
Jsp生成不了PDF的問題
問題描述:運行自帶的web(webapp目錄下)例子時(我使用的服務器是TomCat),用Servlet生成PDF完全沒問題,而JSP方式卻報getOutputStream() has already been called for this response 的錯,看JSP源碼發現和Servlet差不多。
問題原因:Tomcat首先執行.jsp文件開始的Java代碼,然後準備session, out等變量。而輸出PDF的代碼出現在.jsp文件開始的<% ... %>段中,這樣HttpServerletResponse的getOutputStream()方法已被調用。在JSP規範中定義此方法只能被調用一次,這樣當Tomcat準備out變量時必然會出錯。
所以基於TomCat的服務器都會出錯,如Jboss, Sun ONE AppServer
解決方法:很簡單,按照JSP/Servlet規範定義輸出非文本內容,如圖片、聲音等應該使用Servlet而不是JSP。在Servlet中輸出流完全由應用程序按需打開/關閉。
雖然彷彿這不叫解決方法,但我查了很多地方,也沒有找到更好的說法,所以大家做JasperReport還是用Servlet好了
生成HTML時JRHtmlExporterParameter.IMAGES_MAP的問題
這算不得一個問題,只是當時我有點迷惑,就拿出來說說好了。
不知大家注意過沒有,每次生成Html時,都有下面一段:
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Map imagesMap = new HashMap();
session.setAttribute("IMAGES_MAP", imagesMap);
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out);
exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, imagesMap);
exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, "image.jsp?image=");
特別是:
exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out);
exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, imagesMap);
exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, "image.jsp?image=");
這幾句,感覺莫名其妙的,
最初猜想是顯示圖片用的,可到底是不是呢?
而且生成的Html頁面的源碼中,有很多
<td><img src="image?image=px" width=40 height=1></td>
到底px是什麼樣的圖片?
查看javadoc,寫的過於簡單,根本沒有說明。於是,看源碼:
his.imagesMap = (Map)this.parameters.get(JRHtmlExporterParameter.IMAGES_MAP);
if(this.imagesMap == null)
{
this.imagesMap = new HashMap();
}
………….
this.loadedImagesMap = new HashMap();
byte[] pxBytes = JRImageLoader.loadImageDataFromLocation("dori/jasper/engine/images/pixel.GIF");
this.loadedImagesMap.put(pxBytes, "px");
this.imagesMap.put("px", pxBytes);
哈哈,原形畢露了,原來px就是dori/jasper/engine/images/pixel.GIF(一個小不點),但它對網頁的美觀起了很大的作用,不信你寫錯Image(jsp、servlet)的路徑看看(這也是個可能出錯的地方)。
中文顯示的問題
問題描述:生成的Html或PDF中文顯示爲亂碼或不顯示
解決方法(HTML):
如果只要求生成Html(可能不會有這麼簡單就能打發走的客戶),很好辦,如果是JSP: <%@ page contentType="text/html;charset=GB2312" %>
如果是Servlet:response.setContentType("text/html;charset=GB2312");
哈哈,大功告成,預知PDF的中文解決方法,請撥打收費諮詢電話110。
解決方法(PDF):
大家把手上的板磚放下吧,我說還不行嗎,只是不知道這是不是正確或比較好的解決方法,請多指點。
由於生成PDF時沒有什麼地方可以設置charset=GB2312(真是個天才的傻想法)。
我們分三步走好了。
1.由於JasperReport使用iText生成PDF,所以我們需要iText亞洲語言包
http://itext.sourceforge.net/downloads/iTextAsian.jar.
將他放在lib中。
2.在JasperReport的設計xml中,可以定義一箇中文Font:
<reportFont name="Arial_Normal" isDefault="true" fontName="Arial" size="12" pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H" isPdfEmbedded="true"/>
其中pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H"的就是iTextAsian.jar包中定義的字體了。
3.漢字都用UTF-8編碼
iReport保存的漢字都是UTF-8編碼
還可以使用UltraEdit,只需菜單Advanced – Configuration… - General 勾選 Auto detect UTF-8 files – (On),就可以用它編輯UTF-8編碼的漢字了。
圖片顯示的實現方法(JFreeChart)
所謂Report,圖片自然必不可少,特別是所謂的chart,例子裏有chart的實現,其實那只是實現的一種方法,將chart定義爲variable,然後在ChartScriptlet.java(Scriptlet.)中生成chart,setVariableValue。
其實我們可以看到,由於JasperReport本身不帶Chart功能,所以她(請容許我使用”她”,誰讓我是光棍程序員呢,嘿嘿)的chart都是依靠別的工具生成,然後作爲variable或者parameter傳遞的。這樣我們就可以隨心所欲的讓她顯示任何BufferedImage了,嘿嘿,管他是JfreeChart生成的還是靜態image。
我比較傾向於定義爲parameter,因爲可以在生成JRDataSource的同一個程序中得到Chart的數據,免去Scriptlet裏的數據庫操作,或者如果是簡單報表,直接Scriptlet都省了。
我的通用 .jasper 生成方法
JasperReport自帶的範例都是用ant構建的,但每個範例有不同的build.xml和.class,那麼能不能有一個統一的構件程序呢?iReport可以,但他每次都會寫所有的屬性,顯得頁面很不整潔、明瞭,所以我修改了一個範例的build.xm.和.class,來構建我的JasperReport。有興趣的同道可以看看。
1.在build.xml中定義
<property name="filename" value="" />
用於動態傳遞文件名
2.替換所有的 <arg value="-F*******.xml"/>爲<arg value="-F${filename}.xml"/>
3.修改程序,每次FILL時都傳JREmptyDataSource進去。
每次build時,只需在以前的基礎上加上參數:
-Dfilename=******
如:ant compile -Dfilename="myDemo"