1

我正在使用带有 IText 的 Flying Saucer,以便从 HTML 文件生成 PDF,特别是利用org.xhtmlrenderer.pdf.ITextRenderer该类。我的代码很简单。生成代码被封装在这样的方法中:

/* PDfGenerator class only has ONE instance */
public PdfGenerator() {
    this.renderer = new ITextRenderer(); //This is a class variable that only gets instantiated ONCE
}

public void generatePDF(String outputFilePath, String htmlContent) {
    renderer.setDocumentFromString(htmlContent);
    renderer.layout();
    renderer.createPDF(new BufferedOutputStream(
          new FileOutputStream(new File(outputFilePath)), BUFFER_SIZE), true);
    renderer.finishPDF();
}

编辑:

我的生成器类实际上是由 Spring 作为单例对象管理的。我有一个管理器类,它有一个 ExecutorService 作为 PDF 生成任务的队列。该管理器使用单例生成器来生成对象。因此,我只实例化 ITextRenderer 一次并重用它。现在我将队列设置为同时操作最多 2 个线程。我刚刚意识到这是否可能导致了这种情况,因为我遇到了两个线程正在使用我的一个渲染器来渲染两组单独的 PDF 的情况。

现在,我才意识到我实际上每次渲染都调用了两次“完成”!一个在createPDF()错误调用中(传递 true 作为第二个参数),一个显式调用finishPDF().

这已经运行了很长一段时间,并且大部分时间都成功地生成了 PDF 。我偶尔会遇到两种不同类型的错误:

  1. 由于不平衡的保存/恢复状态运算符而导致的运行时异常。示例堆栈跟踪如下:

    java.lang.RuntimeException: Unbalanced save/restore state operators.
    at com.lowagie.text.pdf.PdfContentByte.restoreState(Unknown Source) ~[itext-2.0.8.jar:na]
    at org.xhtmlrenderer.pdf.ITextOutputDevice.setClip(ITextOutputDevice.java:737) ~[core-renderer-R8.jar:na]
    at org.xhtmlrenderer.pdf.ITextRenderer.paintPage(ITextRenderer.java:387) ~[core-renderer-R8.jar:na]
    at org.xhtmlrenderer.pdf.ITextRenderer.writePDF(ITextRenderer.java:348) ~[core-renderer-R8.jar:na]
    at org.xhtmlrenderer.pdf.ITextRenderer.createPDF(ITextRenderer.java:315) ~[core-renderer-R8.jar:na]
    at org.xhtmlrenderer.pdf.ITextRenderer.createPDF(ITextRenderer.java:280) ~[core-renderer-R8.jar:na]
    
  2. 生成的 PDF 有缺失/变形的部分,或者最坏的情况是空白页。

对于问题 2,我相当有信心这是由于调用了 finishPDF() 两次。但是,对于问题 1,它发生对 finishPDF() 的调用执行之前,所以我实际上不知道这是否是导致问题的原因。

有没有人在将飞碟与 iText 一起使用时处理这两个问题的经验?

4

1 回答 1

1

我遇到的问题基本上是在不同的线程上同时访问同一个 ITextRenderer 实例,从而弄乱了当前正在运行的 PDF 生成作业的处理。

我已经让 Executor 服务只使用 1 个线程并使生成作业按顺序进行,根据我的观察,只要我一次处理一个,我就可以重用相同的 ITextRenderer。

我已经向飞碟库的开发人员发送了一个查询以确认这一点,我会在他们回复时更新这篇文章。

顺便说一句,我只需要弄清楚使用 1 个线程和 1 个预实例化的 ITextRenderer 实例生成或使用多个线程但每个线程实例化 ITextRenderer 是否更有效。

于 2012-09-27T02:34:33.860 回答