本文目录导读:

在Java中生成PDF文件有多种方式,以下是几种主流方案的对比和具体实现案例:
主流方案对比
| 方案 | 特点 | 适用场景 |
|---|---|---|
| iText | 功能强大,支持HTML转PDF | 企业级应用,复杂PDF |
| Apache PDFBox | 开源免费,操作底层 | 简单PDF创建/编辑 |
| JasperReports | 基于模板,支持数据源 | 报表类应用 |
| Flying Saucer | HTML+CSS转PDF | 前端样式复杂场景 |
iText实现案例(最常用方案)
添加Maven依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version> <!-- 支持中文 -->
</dependency>
基本PDF生成示例
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import java.io.FileOutputStream;
public class PdfGenerator {
public static void main(String[] args) throws Exception {
// 1. 创建文档对象
Document document = new Document(PageSize.A4, 50, 50, 50, 50);
// 2. 创建PDF写入器
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream("example.pdf"));
// 3. 打开文档
document.open();
// 4. 设置中文字体
BaseFont bfChinese = BaseFont.createFont(
"STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font chineseFont = new Font(bfChinese, 12, Font.NORMAL);
// 5. 添加内容
document.add(new Paragraph("Hello PDF! 你好,PDF!", chineseFont));
document.add(new Paragraph("这是第一段文字。", chineseFont));
// 添加表格
PdfPTable table = new PdfPTable(3);
table.addCell(new PdfPCell(new Phrase("姓名", chineseFont)));
table.addCell(new PdfPCell(new Phrase("年龄", chineseFont)));
table.addCell(new PdfPCell(new Phrase("城市", chineseFont)));
table.addCell("张三");
table.addCell("25");
table.addCell("北京");
document.add(table);
// 6. 关闭文档
document.close();
System.out.println("PDF生成成功!");
}
}
使用HTML模板生成PDF
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
public class HtmlToPdf {
public static void main(String[] args) throws Exception {
String htmlContent = """
<html>
<body style="font-family: SimSun;">
<h1>用户信息表</h1>
<table border="1" cellpadding="5">
<tr>
<th>姓名</th>
<th>年龄</th>
<th>邮箱</th>
</tr>
<tr>
<td>张三</td>
<td>28</td>
<td>zhangsan@example.com</td>
</tr>
<tr>
<td>李四</td>
<td>32</td>
<td>lisi@example.com</td>
</tr>
</table>
</body>
</html>
""";
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream("user_report.pdf"));
document.open();
// 解析HTML到PDF
XMLWorkerHelper.getInstance().parseXHtml(
writer, document,
new ByteArrayInputStream(htmlContent.getBytes("UTF-8")));
document.close();
System.out.println("HTML已成功转换为PDF!");
}
}
Apache PDFBox实现案例
添加依赖
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.27</version>
</dependency>
创建PDF文档
import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.pdmodel.font.*;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import java.io.IOException;
public class PdfBoxExample {
public static void main(String[] args) throws IOException {
// 1. 创建文档
PDDocument document = new PDDocument();
// 2. 创建页面
PDPage page = new PDPage(PDRectangle.A4);
document.addPage(page);
// 3. 获取内容流
PDPageContentStream contentStream = new PDPageContentStream(document, page);
// 4. 设置字体(加载中文字体)
PDFont font = PDType0Font.load(document,
new File("C:/Windows/Fonts/simsun.ttc")); // 宋体
// 5. 开始文本
contentStream.beginText();
contentStream.setFont(font, 16);
contentStream.setLeading(30f);
contentStream.newLineAtOffset(50, 700);
// 6. 写入内容
contentStream.showText("Hello PDFBox!");
contentStream.newLine();
contentStream.showText("这是中文文本。");
contentStream.newLine();
contentStream.showText("日期:" + new java.util.Date());
// 7. 结束文本
contentStream.endText();
contentStream.close();
// 8. 保存文档
document.save("pdfbox_example.pdf");
document.close();
System.out.println("PDFBox PDF生成成功!");
}
}
JasperReports报表生成(适合复杂报表)
创建JRXML模板文件 report_template.jrxml
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports
http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
name="UserReport" pageWidth="595" pageHeight="842" columnWidth="535"
leftMargin="30" rightMargin="30" topMargin="20" bottomMargin="20">
<parameter name="Title" class="java.lang.String"/>
<band height="30">
<staticText>
<reportElement x="0" y="0" width="535" height="20"/>
<textElement textAlignment="Center">
<font size="16" isBold="true"/>
</textElement>
<text><![CDATA[$P{Title}]]></text>
</staticText>
</band>
</title>
<detail>
<band height="20">
<textField>
<reportElement x="0" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="100" y="0" width="100" height="20"/>
<textFieldExpression><![CDATA[$F{age}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="200" y="0" width="335" height="20"/>
<textFieldExpression><![CDATA[$F{email}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
Java代码生成报表
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import java.util.*;
public class JasperReportExample {
public static void main(String[] args) throws Exception {
// 准备数据
List<Map<String, Object>> dataList = new ArrayList<>();
Map<String, Object> user1 = new HashMap<>();
user1.put("name", "张三");
user1.put("age", 28);
user1.put("email", "zhangsan@example.com");
dataList.add(user1);
Map<String, Object> user2 = new HashMap<>();
user2.put("name", "李四");
user2.put("age", 32);
user2.put("email", "lisi@example.com");
dataList.add(user2);
// 创建数据源
JRDataSource dataSource = new JRBeanCollectionDataSource(dataList);
// 设置参数
Map<String, Object> parameters = new HashMap<>();
parameters.put("Title", "用户信息报表");
// 编译模板
JasperReport jasperReport = JasperCompileManager
.compileReport("report_template.jrxml");
// 填充数据
JasperPrint jasperPrint = JasperFillManager
.fillReport(jasperReport, parameters, dataSource);
// 导出PDF
JasperExportManager.exportReportToPdfFile(
jasperPrint, "jasper_report.pdf");
System.out.println("JasperReport PDF生成成功!");
}
}
最佳实践建议
选择建议
- 简单PDF:使用PDFBox,轻量级,无需商业许可
- 复杂排版:使用iText,功能最全面
- 报表场景:使用JasperReports,支持可视化设计
- HTML转PDF:使用Flying Saucer或iText的HTML解析
中文支持注意事项
- iText:使用
itext-asian包,或手动加载中文字体 - PDFBox:必须加载中文字体文件(如simsun.ttc)
- 所有方案都建议使用支持中文的字体
性能优化
- 使用连接池管理PDF创建
- 大数据量时分页处理
- 考虑字体缓存,避免重复加载
选择哪种方案取决于你的具体需求:如果需要简单快捷,PDFBox是不错的选择;如果需要强大的排版功能,iText是标准答案;如果是报表生成,JasperReports最专业。