《實戰錄》導語
雲端衛士《實戰錄》欄目定期會向冬粉朋友們分享一些在開發運維中的經驗和技巧,2017年我們將一如既往地為朋友們奉獻更多優質內容。本期分享人為雲端衛士安全運營工程師史懷周,主要介紹Java中多重格式報表導出方案比較。
系統中經常存在導出報告的需求,而導出的框架五花八門,該如何選擇呢?
本文對幾種常見的框架進行比較,希望可以在遇到導出需求時,為你提供一些參考。常見的導出格式包括Word、 Excel和PDF等,下面針對對這三種格式進行說明。
Word
Word一般用於導出包含圖片,表格等的分析匯總類報告。
1.JACOB
jacob的原理是使用自帶的DLL動態鏈接庫,通過JNDI的方式實現對COM程序的調用。它要求主機必須是Windows平台,當大量請求同時操作時,有一定幾率做成office資源的死鎖。種種情況都是我們不能接受的,所以適用面不廣。
2.java2word
java2word是通過java api調用MS Office文檔的組件。可以實現打開文檔,創建文檔,插入圖片,創建表格等多種操作。但同樣的,必須要在Windows平台上才能使用。所以也不納入考慮範圍。
3.POI
POI出了可以導出Excel,還可以導出Word。相信很多人壓根沒有想到,但是POI對word的支持十分有限,不能設置樣式。如果導出的報表格式比較複雜,這種方案也是愛莫能助的。
4.FreeMarker
Freemarker是模板工具,而word是文檔,兩者如何搭配呢?其實很簡單。word允許通過Office轉換成標準XML格式,而word中的內容就是一個個的xml標籤。
所以我們可以先用office製作word模板,另存為xml之後,將其中的需要動態生成的部分改成變數,再通過freemarker生成即可(注意生成的文件後綴名要改為.doc或.docx)。而word中的圖片該怎麼處理呢?word中的圖片是以base64存儲的,所以只要將圖片轉換為base64,然後放在對應的變數上就可以了。
這種方式的最大缺點是word轉為xml格式后,結構相對複雜,模板的製作比較麻煩。但綜合來說,這是最佳的Word導出方案。
Excel
Excel通常用來導出數據類型的報表。比如某段時間內的DDoS攻擊流量匯總等。Excel的導出比較常見,網上案例也比較多,大部分都使用JXL或POI這兩個工具。
1.JXL
JXL對中文支持很好,且操作簡單。支持圖片和圖表,但是支持有限,而且圖片只支持PNG格式。大數據量Excel導出時的效率較差。
2.POI
POI在Excel導出中應該是最常用的方案了。它對Excel的很全面,支持使用公式、宏。對格式支持很好,可以任意定義單元格的格式。同時在大數據量Excel的生成上,效率很高。
PDF1.jasper report
jasper report是比較常用的一種生成PDF的方式。它的設計思路是先生成模板,再將數據嵌入模板中。它的缺點是模板生成複雜,規則眾多,需要藉助IDE的可視化工具進行編輯,入門和使用都比較困難。
2.itext
iText是十分好用的一個PDF開源軟體。支持使用圖片、HTML頁面和直接用Java代碼等多種方式生成PDF。IText的API很豐富,對PDF的格式支持很好。iText有一個顯著的缺點,對HTML的格式要求特別嚴格,且無法識別很多html的tag和attribute,無法識別css,需要使用API函數來設置樣式。如果想要使用HTML直接生成PDF,IText的缺點確認是讓人抓狂。在HTML上畫樣式要比使用API一行一行繪製PDF樣式簡單的多。怎麼辦呢?如果你有一個可訪問的頁面地址,你可以試試使用下面的方式。
3.iText+phantomjs
PhantomJS 是一個基於 WebKit 的伺服器端 JavaScript API。PhantomJS可以用於頁面自動化,網路監測,網頁截屏,以及無界面測試等。我們可以通過它對要生成PDF的URL截屏,然後將圖片轉成PDF。這種方式的缺點是,生成的PDF內的文字全部不可選中,沒辦法複製其中內容。
4.iText+flying sauser
flying sauser是基於IText的一個開源軟體。它解決了iText對HTML支持弱的痛點。而且生成的PDF內容全部可以選中複製。缺點是它仍然對HTML格式要求嚴格。
文件開頭必須是
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">
所有的標籤必須閉合。特殊字元需要使用<![CDATA]>括起來。但和前面幾種方案比起來,這仍然算是比較優秀的解決方案了。b( ̄▽ ̄)d