在Java开发中,打印HTML内容的需求常见于企业报表、票据生成、文档导出等场景,实现HTML打印的核心在于将HTML文档转换为可打印的格式,并通过Java的打印API或第三方工具完成输出,本文将介绍几种主流的实现方法,涵盖简单场景到复杂布局的处理技巧。

基于Java Print Service API的简单打印
Java内置的Java Print Service(JPS) API提供了基础的打印功能,适合处理已渲染为可打印对象(如图像、文本)的HTML内容,其核心流程包括获取打印服务、设置打印属性、将HTML转换为可打印格式,并触发打印任务。
需将HTML文档转换为java.awt.print.Printable对象,对于简单HTML,可通过javax.swing.text.html.HTMLEditorKit解析HTML文档,并利用javax.swing.text.View将其渲染为图形。
HTMLEditorKit kit = new HTMLEditorKit();
HTMLDocument doc = (HTMLDocument) kit.createDefaultDocument();
kit.read(new StringReader(htmlContent), doc, 0);
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(new Printable() {
public int print(Graphics g, PageFormat pf, int pageIndex) {
if (pageIndex > 0) return NO_SUCH_PAGE;
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
doc.print(g2d);
return PAGE_EXISTS;
}
});
job.print();
此方法适用于纯HTML且无需复杂样式控制的场景,但缺点是对CSS支持有限,且无法直接处理分页、页眉页脚等打印专用样式。
使用Flying Saucer处理复杂HTML
对于需要完整CSS支持(包括打印样式、分页规则)的复杂HTML,推荐使用开源库Flying Saucer(基于xhtmlrenderer),它可将HTML直接渲染为BufferedImage或PDF,再结合打印API输出。

首先添加依赖(Maven):
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.22</version>
</dependency>
核心代码如下:
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(htmlContent);
renderer.layout();
// 渲染为图像后打印
BufferedImage image = renderer.getImage();
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(new Printable() {
public int print(Graphics g, PageFormat pf, int pageIndex) {
if (pageIndex > 0) return NO_SUCH_PAGE;
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(image, (int) pf.getImageableX(), (int) pf.getImageableY(), null);
return PAGE_EXISTS;
}
});
job.print();
// 或直接渲染为PDF后打印(需PDF打印支持)
OutputStream os = new FileOutputStream("output.pdf");
renderer.createPDF(os);
os.close();
Flying Saucer的优势在于对CSS 2.1和部分CSS 3的支持,包括@media print样式、分页属性(page-break-before)等,适合打印带有复杂布局的HTML文档。
动态HTML生成与打印实践
在实际应用中,HTML内容常需动态生成(如结合数据库数据),此时可结合模板引擎(如Thymeleaf、Freemarker)生成HTML,再通过上述方法打印,以Thymeleaf为例:

- 定义模板(
template.html):<!DOCTYPE html> <html> <head> <style> @media print { .no-print { display: none; } @page { margin: 1cm; } } </style> </head> <body> <h1>订单详情</h1> <p>订单号:<span th:text="${orderNo}"></span></p> <table border="1"> <tr><th>商品</th><th>数量</th></tr> <tr th:each="item : ${items}"> <td th:text="${item.name}"></td> <td th:text="${item.quantity}"></td> </tr> </table> <button class="no-print" onclick="window.print()">打印</button> </body> </html> - 渲染模板并打印:
Context context = new Context(); context.setVariable("orderNo", "ORD2026001"); context.setVariable("items", Arrays.asList( new Item("商品A", 2), new Item("商品B", 1) ));
TemplateEngine engine = new TemplateEngine();
String html = engine.process(“template.html”, context);
// 使用Flying Saucer打印
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(html);
renderer.layout();
renderer.createPDF(new FileOutputStream(“order.pdf”));
通过模板引擎,可灵活嵌入动态数据,并通过CSS控制打印时的显示隐藏(如隐藏按钮等非打印元素)。
### 四、打印优化与注意事项
1. **样式适配**:使用`@media print`定义打印专用样式,如调整页边距(`margin`)、隐藏非必要元素(`.no-print { display: none; }`)、设置背景色为白色(避免墨 waste)。
2. **分页控制**:通过`page-break-before: always;`强制分页,或`page-break-inside: avoid;`避免表格、图片被拆分。
3. **字体与编码**:确保HTML使用`UTF-8`编码, Flying Saucer需指定字体路径(`renderer.getFontResolver().addFont("font.ttf", "UTF-8", true);`)以避免乱码。
4. **异常处理**:捕获`PrinterAbortException`、`PrinterException`等异常,处理打印机不可用或打印失败的情况。
通过以上方法,可根据需求选择适合的技术方案:简单场景用JPS API,复杂布局用Flying Saucer,动态数据结合模板引擎,合理运用CSS打印样式和异常处理,可实现高效、稳定的HTML打印功能。

















