JSP文件如何转换为PDF:详细步骤与工具推荐

概述

JSP(JavaServer Pages)是一种动态网页技术,常用于生成HTML内容。但在许多业务场景中(如生成报告、发票、合同等),我们需要将JSP生成的页面内容保存为PDF文件。本文将介绍几种将JSP转换为PDF的实用方法,涵盖主流Java库(iText、Flying Saucer、Apache FOP),并提供代码示例和关键步骤。

方法一:使用iText从JSP输出直接生成PDF

iText是一个强大的PDF操作库,可以通过解析JSP生成的HTML字符串来创建PDF。基本思路是:在JSP中渲染出HTML内容,然后通过HTTP响应或字符串传递,最后使用iText的HtmlConverter类进行转换。

步骤

  1. 在JSP中生成HTML内容(例如通过JSTL、表达式等)。
  2. 获取HTML字符串(可通过请求转发或直接输出到字符串缓冲区)。
  3. 使用iText的HtmlConverter.convertToPdf()方法将HTML转为PDF。
// 示例代码(Servlet或Controller中)
String htmlContent = "<html><body><h1>Hello, PDF!</h1></body></html>";
OutputStream os = response.getOutputStream();
HtmlConverter.convertToPdf(htmlContent, os);
os.close();

注意事项

  • iText的HTML转PDF功能对CSS支持有限,复杂布局可能变形。
  • 建议使用HtmlConverter.convertToPdf()时设置ConverterProperties以调整字体等。

方法二:使用Flying Saucer(基于iText)渲染XHTML

Flying Saucer是基于iText的XHTML/CSS渲染引擎,能更好地支持CSS样式,特别适合将JSP输出的XHTML转换为PDF。它要求输入为格式良好的XHTML(XML兼容)。

步骤

  1. 确保JSP输出符合XHTML标准(例如使用XHTML DOCTYPE,闭合标签等)。
  2. 在Servlet中获取JSP渲染后的XHTML字符串。
  3. 使用Flying Saucer的ITextRenderer渲染成PDF。
// 示例代码
String xhtml = "..."; // 获取JSP输出的XHTML
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(xhtml);
renderer.layout();
OutputStream os = response.getOutputStream();
renderer.createPDF(os);
os.close();

优势与局限

优势:CSS支持较好,适合复杂样式;局限:必须使用XHTML,且对JavaScript无效。

方法三:使用Apache FOP转换JSP生成的XML/XSL-FO

Apache FOP(Formatting Objects Processor)是一个专业的XSL-FO处理器,能将XML数据结合XSL-FO样式表生成PDF。这种方法适合报表生成场景:JSP仅作为数据展示层,实际转换在服务端完成。

步骤

  1. 在JSP中生成XML数据(或直接使用JavaBean/DAO获取数据)。
  2. 编写XSL-FO模板文件(描述页面布局、字体等)。
  3. 在Servlet中利用FOP API将XML和XSL-FO合并输出PDF。
// 示例代码片段
File xsltFile = new File("template.xsl");
InputStream xmlStream = ...; // 从JSP或数据源获取XML
FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
OutputStream os = response.getOutputStream();
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, os);
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(xsltFile));
Source src = new StreamSource(xmlStream);
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
os.close();

适用场景

适合需要高度定制化布局和分页的文档(如发票、产品目录),但学习曲线较陡。

总结与选择建议

  • 简单场景:若JSP页面布局简单,使用iText的HtmlConverter快速集成。
  • 注重CSS样式:选择Flying Saucer,保持XHTML规范。
  • 复杂文档报表:采用Apache FOP + XML/XSL-FO方案,获得最佳控制。

无论哪种方法,建议将PDF生成逻辑放在Servlet或服务层中,而非直接在JSP中处理,以保持职责分离。此外,注意中文显示可能需要设置字体嵌入,避免乱码。