当前位置: 代码迷 >> PowerDesigner >> JAVA PDF 生验方案
  详细解决方案

JAVA PDF 生验方案

热度:5105   发布时间:2013-02-26 00:00:00.0
JAVA PDF 生成方案

Jasper Report

看到的市面上采用的最多的方案,是Jasper Report。相关的文档也很多,不过很杂,需要完全掌握,我认为还是有些坡度和时间的。这个时间和坡度我认为主要来自于对iReport这个IDE的反复尝试,对里面的每个属性的摸索。

Jasper Report的设计思路,本身是不违反我上面所说的初衷的。因为我们的努力方向是先生成模板,然后得到数据,最后将两者整合得到结果。但是Jasper Report的问题在于,其生成模板的方式过于复杂,即使有IDE的帮助,我们还是需要对其中的众多规则有所了解才行,否则就会给调试带来极大的麻烦。

所以,我认为Jasper Report是一个半调子方案,这种强依赖于IDE进行可视化编辑的方式令我很不爽。同时,由此带来的诸多的限制,相信也让很多使用者颇为头疼。在经历了一番痛苦的挣扎后,决定放弃使用这种方案。

iText

其实Jasper Report是基于iText的。于是有的人会说,那么直接使用iText不是一种倒退么?的确,直接使用iText似乎就需要直接使用原生的API进行编程了。不过幸好iText其实提供了一些方便的API,通过使用这些API,我们可以直接将HTML代码转化成iText可识别的Document对象,从而导出PDF文档。

?

java 代码

?

[java] view plaincopyprint?
  1. import?java.io.FileOutputStream;??
  2. import?java.io.FileReader;??
  3. import?java.util.ArrayList;??
  4. ??
  5. import?com.lowagie.text.Document;??
  6. import?com.lowagie.text.Element;??
  7. import?com.lowagie.text.simpleparser.HTMLWorker;??
  8. import?com.lowagie.text.simpleparser.StyleSheet;??
  9. import?com.lowagie.text.pdf.PdfWriter;??
  10. ??
  11. public?class?MainClass?{??
  12. ??public?static?void?main(String[]?args)?throws?Exception?{??
  13. ????Document?document?=?new?Document();??
  14. ????StyleSheet?st?=?new?StyleSheet();??
  15. ????st.loadTagStyle("body",?"leading",?"16,0");??
  16. ????PdfWriter.getInstance(document,?new?FileOutputStream("html2.pdf"));??
  17. ????document.open();??
  18. ????ArrayList?p?=?HTMLWorker.parseToList(new?FileReader("example"),?st);??
  19. ????for?(int?k?=?0;?k?<?p.size();?++k)??
  20. ??????document.add((Element)?p.get(k));??
  21. ????document.close();??
  22. ??}??
  23. }??

?

?

这是从网上找到的一个例子。从代码中,我们可以看到,iText本身提供了一个简单的HTML的解析器,它可以把HTML转化成我们需要的PDF的document。

有了这个东西,基本上我的目标就能达成一大半了。接下来我的任务就是根据实际情况去编写HTML代码,然后扔进这个方法,就OK了。而真正的HTML代码,我们则可以在这里使用真正的模板技术,Freemarker或者Velocity去生成我们所需要的内容。当然,这已经是我们熟门熟路的东西了。

正当我觉得这个方案基本能符合我的要求的时候,我也同样找到了它的很多弱项:

1. 无法识别很多HTML的tag和attribute(应该是iText的HTMLParser不够强大)
2. 无法识别CSS

如果说第一点我还可以勉强接受的话,那么第二点我就完全不能接受了。无法识别简单的CSS,就意味着HTML失去了最基本的活力,也无法根据实际要求调整样式。

所以这种方案也必然无法成为我的方案。

flying sauser

在这种情况下,我几乎已经燃起了自己编写一个支持CSS解析的HTML Parser的想法。幸好,在一个非常偶然的情况下,我在google中搜到了这样一个开源项目,它能够满足我的一切需求。这就是flying sauser,项目主页是:https://xhtmlrenderer.dev.java.net/

项目的首页非常吸引人:An XML/XHTML/CSS 2.1 Renderer。这不正是我要的东西么?

仔细再看里面的文档:

引用
Flying Saucer is an XML/CSS renderer, which means it takes XML files as input, applies formatting and styling using CSS, and generates a rendered representation of that XML as output. The output may go to the screen (in a GUI), to an image, or to a PDF file. Because we believe most people will be interested in re-using their knowledge of web layout, our main target for content is XHTML 1.0 (strict), an XML document format that standardizes HTML.

完美了。这东西能解析HTML和CSS,而且能输出成image,PDF等格式。哇!我们来看看sample代码(代码丑陋,不过已经能说明问题了):?

?

[java] view plaincopyprint?
  1. /*????
  2. *?ITextRendererTest.java?*????
  3. *?Copyright?2009?Shanghai?TuDou.?????
  4. *?All?rights?reserved.????
  5. */????
  6. ????
  7. package?itext;?????
  8. ????
  9. import?java.io.File;?????
  10. import?java.io.FileOutputStream;?????
  11. import?java.io.OutputStream;?????
  12. ????
  13. import?org.xhtmlrenderer.pdf.ITextFontResolver;?????
  14. import?org.xhtmlrenderer.pdf.ITextRenderer;?????
  15. ????
  16. import?com.lowagie.text.pdf.BaseFont;?????
  17. ????
  18. /**????
  19. ?*?TODO?class?description?*????
  20. ?*???
  21. ?*?@author?pcwang???
  22. ?*???
  23. ?*?@version?1.0,?上午11:03:26??create?$Id$???
  24. ?*/????
  25. public?class?ITextRendererTest?{?????
  26. ????public?static?void?main(String[]?args)?throws?Exception?{?????
  27. ????????String?inputFile?=?"conf/template/test";?????
  28. ????????String?url?=?new?File(inputFile).toURI().toURL().toString();?????
  29. ????????String?outputFile?=?"firstdoc.pdf";?????
  30. ????????OutputStream?os?=?new?FileOutputStream(outputFile);?????
  31. ????????ITextRenderer?renderer?=?new?ITextRenderer();?????
  32. ????????renderer.setDocument(url);?????
  33. ????
  34. ????????//?解决中文支持问题??? ??
  35. ????????ITextFontResolver?fontResolver?=?renderer.getFontResolver();?????
  36. ????????fontResolver.addFont("C:/Windows/Fonts/arialuni.ttf",?BaseFont.IDENTITY_H,?BaseFont.NOT_EMBEDDED);?????
  37. ????
  38. ????????//?解决图片的相对路径问题??? ??
  39. ????????renderer.getSharedContext().setBaseURL("file:/D:/Work/Demo2do/Yoda/branch/Yoda%20-%20All/conf/template/");?????
  40. ?????????????
  41. ????????renderer.layout();?????
  42. ????????renderer.createPDF(os);?????
  43. ?????????????
  44. ????????os.close();?????
  45. ????}?????
  46. }????
?
运行,成功!实在太简单了!API帮你完成了一切!

有了这个东西,我们就可以将PDF的生成流程变成这样:

1) 编写Freemarker或者Velocity模板,打造HTML,勾画PDF的样式(请任意使用CSS)

2) 在你的业务逻辑层引入Freemarker的引擎或者Velocity的引擎,并将业务逻辑层中可以获取的数据和模板,使用引擎生成最终的内容

3) 将我上面的sample代码做简单封装后,调用,生成PDF

这样,我想作为一个web程序员来说,上面的3点,都不会成为你的绊脚石。你可以轻松驾驭PDF了。

在Flying Saucer的官方文档中,有一些Q&A,可以解决读者们大部分的问题。包括PDF的字体、PDF的格式、Image如何处理等等。大家可以尝试着去阅读。?
  相关解决方案