家电Web应用中,如何从现有JSP生成可下载PDF订单报表?
当然可以!直接把JSP输出转成PDF的方案
你完全不需要手动用iText从零构建PDF内容——捕获JSP渲染后的HTML并转换为PDF是更高效且贴合你现有开发流程的方案,我来给你详细拆解实现步骤:
核心思路
- 捕获JSP渲染后的完整HTML内容(替代直接输出到浏览器)
- 将捕获到的HTML转换为PDF文件,作为下载响应返回给用户
步骤1:捕获JSP的HTML输出
我们可以通过自定义HttpServletResponseWrapper来拦截JSP的输出流,把渲染后的HTML保存为字符串。
自定义响应包装类
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import java.io.CharArrayWriter; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletOutputStream; public class HtmlCaptureResponseWrapper extends HttpServletResponseWrapper { private final CharArrayWriter charArrayWriter = new CharArrayWriter(); public HtmlCaptureResponseWrapper(HttpServletResponse response) { super(response); } // 覆盖getWriter,将输出写入CharArrayWriter @Override public PrintWriter getWriter() throws IOException { return new PrintWriter(charArrayWriter); } // 覆盖getOutputStream,处理字节流输出 @Override public ServletOutputStream getOutputStream() throws IOException { return new ServletOutputStream() { @Override public void write(int b) throws IOException { charArrayWriter.write(b); } }; } // 获取捕获到的HTML内容 public String getCapturedHtml() { return charArrayWriter.toString(); } }
步骤2:在Servlet中处理PDF生成请求
当用户点击“生成PDF”按钮时,对应的Servlet会先转发到订单报表JSP捕获HTML,再用HTML转PDF工具生成可下载的PDF文件。
Servlet核心代码
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.xhtmlrenderer.pdf.ITextRenderer; import java.io.IOException; @WebServlet("/generateOrderPdf") public class OrderPdfGeneratorServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 捕获JSP渲染的HTML内容 HtmlCaptureResponseWrapper responseWrapper = new HtmlCaptureResponseWrapper(response); // 转发到你的订单报表JSP(替换为实际路径) request.getRequestDispatcher("/WEB-INF/views/order-report.jsp").forward(request, responseWrapper); String capturedHtml = responseWrapper.getCapturedHtml(); // 2. 配置PDF下载响应头 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=\"order-report-" + System.currentTimeMillis() + ".pdf\""); // 3. 使用Flying Saucer + iText7将HTML转PDF ITextRenderer renderer = new ITextRenderer(); // 加载捕获到的HTML renderer.setDocumentFromString(capturedHtml); // 渲染布局 renderer.layout(); // 生成PDF并写入响应输出流 renderer.createPDF(response.getOutputStream()); renderer.finishPDF(); } }
步骤3:添加依赖(Maven示例)
推荐使用Flying Saucer(一款纯Java的HTML/CSS到PDF渲染工具)配合iText7,无需额外安装软件:
<!-- Flying Saucer核心库 --> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-core</artifactId> <version>9.1.22</version> </dependency> <!-- Flying Saucer对iText7的适配 --> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf-itext7</artifactId> <version>9.1.22</version> </dependency> <!-- iText7核心依赖(通过pom导入所有子模块) --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext7-core</artifactId> <version>7.2.5</version> <type>pom</type> </dependency>
关键注意事项
- 确保JSP输出标准XHTML:Flying Saucer对HTML的兼容性不如浏览器,建议给JSP添加
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">声明,并且所有标签闭合、属性值加引号。 - CSS兼容性:支持大部分CSS2.1属性,CSS3的部分属性(如flexbox)可能有限支持,建议用基础CSS样式控制报表布局。
- 资源路径问题:如果JSP中引用了图片、CSS文件,需要将路径转为绝对路径,或者在渲染时通过
renderer.getSharedContext().setBaseURL()设置基础路径,确保资源能被正确加载。
内容的提问来源于stack exchange,提问作者A.Martinez
相关产品推荐
相关产品推荐

