在Java中开发发票导出PDF功能,有多种成熟可靠的方式。下面我将为你介绍几种主流的实现方案,并提供选择建议。
| 特性/库 | iText | Apache PDFBox | JasperReports |
|---|---|---|---|
| 主要优势 | 功能全面,API丰富,支持复杂文档(文本、图片、表格、表单、水印、加密等) | Apache开源项目,专注于PDF处理和内容提取,支持创建、修改和提取文本、图片 | 强大的报表生成引擎,基于模板设计,支持多种数据源,特别适合复杂、格式固定的报表 |
| 许可协议 | AGPL(开源),商业用途需购买许可 | Apache License 2.0 (完全免费) | Eclipse Public License |
| 最佳适用场景 | 需要高质量、复杂布局的PDF,如精密报表、发票、合同 | 需要处理现有PDF、提取内容或进行基础生成,且要求完全免费开源的场景 | 基于数据生成结构化报表,如业务报表、图表,且希望模板与代码分离 |
| 学习曲线 | 较陡峭 | 适中 | 适中(需学习模板设计工具) |
📌 准备工作:添加 Maven 依赖
根据你的选择,在 pom.xml 中添加相应依赖。
iText:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.2.5</version> <!-- 请以最新版本为准 -->
</dependency>
Apache PDFBox:
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.24</version> <!-- 请以最新版本为准 -->
</dependency>
JasperReports:
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.17.0</version> <!-- 请以最新版本为准 -->
</dependency>
🧾 实现方式一:使用 iText
iText 功能强大,适合创建布局精确的发票PDF。
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;
import java.io.FileNotFoundException;
public class ITextInvoiceExample {
public static void main(String[] args) {
String dest = "invoice_itext.pdf";
try {
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdfDoc = new PdfDocument(writer);
Document doc = new Document(pdfDoc);
// 1. 添加发票标题
doc.add(new Paragraph("增值税电子发票")
.setTextAlignment(TextAlignment.CENTER)
.setBold().setFontSize(16));
// 2. 添加基本信息表格
Table infoTable = new Table(UnitValue.createPercentArray(new float[]{1, 2, 1, 2}));
infoTable.setWidth(UnitValue.createPercentValue(100));
infoTable.addCell("发票号码");
infoTable.addCell("INV-2025-0918-001");
infoTable.addCell("开票日期");
infoTable.addCell("2025年9月18日");
infoTable.addCell("销售方");
infoTable.addCell("某某科技有限公司");
infoTable.addCell("购买方");
infoTable.addCell("某某有限公司");
doc.add(infoTable);
// 3. 添加商品明细表格(示例)
Table itemTable = new Table(UnitValue.createPercentArray(new float[]{3, 2, 2, 2, 2}));
itemTable.setWidth(UnitValue.createPercentValue(100));
// 表头
itemTable.addHeaderCell("商品名称");
itemTable.addHeaderCell("规格型号");
itemTable.addHeaderCell("单位");
itemTable.addHeaderCell("数量");
itemTable.addHeaderCell("金额");
// 表格内容
itemTable.addCell("软件开发服务");
itemTable.addCell("标准");
itemTable.addCell("项");
itemTable.addCell("1");
itemTable.addCell("¥1000.00");
doc.add(itemTable);
// 4. 添加合计金额、备注等
doc.add(new Paragraph("合计金额:人民币壹仟元整").setBold());
doc.add(new Paragraph("备注:请按时支付"));
doc.close();
System.out.println("iText发票PDF生成成功!");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
🧾 实现方式二:使用 Apache PDFBox
Apache PDFBox 是Apache的开源项目,适合基础PDF生成和处理。
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import java.io.IOException;
public class PDFBoxInvoiceExample {
public static void main(String[] args) {
try (PDDocument document = new PDDocument()) {
PDPage page = new PDPage();
document.addPage(page);
try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
// 设置字体和起始位置
contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);
contentStream.beginText();
contentStream.newLineAtOffset(100, 700);
// 添加发票标题
contentStream.showText("增值税电子发票 - Apache PDFBox生成");
contentStream.newLineAtOffset(0, -30); // 下移30单位
// 添加基本信息
contentStream.setFont(PDType1Font.HELVETICA, 12);
contentStream.showText("发票号码: INV-2025-0918-002");
contentStream.newLineAtOffset(0, -20);
contentStream.showText("开票日期: 2025年9月18日");
contentStream.newLineAtOffset(0, -20);
contentStream.showText("销售方: 某某科技有限公司");
contentStream.newLineAtOffset(0, -20);
contentStream.showText("购买方: 某某有限公司");
contentStream.newLineAtOffset(0, -30);
// 可以继续添加商品明细、金额等信息...
contentStream.showText("商品: 软件开发服务 | 数量: 1 | 金额: ¥1000.00");
contentStream.newLineAtOffset(0, -20);
contentStream.showText("合计金额:人民币壹仟元整");
contentStream.endText();
}
document.save("invoice_pdfbox.pdf");
System.out.println("PDFBox发票PDF生成成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
🧾 实现方式三:使用 JasperReports
JasperReports 基于模板生成报表,适合数据可视化。首先需要用 JasperSoft Studio 设计报表模板 (.jrxml 文件),定义好发票的布局、字段、样式等。
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class JasperReportsInvoiceExample {
public static void main(String[] args) {
try {
// 0. 编译报表模板 (.jrxml -> .jasper)
// JasperCompileManager.compileReportToFile("invoice_template.jrxml"); // 通常可预先编译或运行时编译
// 本例假设已编译好,直接加载
JasperReport jasperReport = JasperCompileManager.compileReport("path/to/invoice_template.jrxml");
// 1. 准备报表参数(如固定信息、统计值等)
Map<String, Object> parameters = new HashMap<>();
parameters.put("INVOICE_TITLE", "增值税电子发票");
parameters.put("SELLER_NAME", "某某科技有限公司");
parameters.put("BUYER_NAME", "某某有限公司");
parameters.put("CURRENT_DATE", "2025年9月18日");
// 2. 准备数据源(如商品明细列表,通常来自数据库查询或业务逻辑)
List<Map<String, Object>> invoiceItems = new ArrayList<>();
Map<String, Object> item1 = new HashMap<>();
item1.put("productName", "软件开发服务");
item1.put("spec", "标准");
item1.put("quantity", 1);
item1.put("unitPrice", 1000.00);
item1.put("totalAmount", 1000.00);
invoiceItems.add(item1);
// ... 可以添加更多商品项
JRBeanCollectionDataSource itemsDataSource = new JRBeanCollectionDataSource(invoiceItems);
parameters.put("ItemDataSource", itemsDataSource); // 通常模板中会定义这个数据源
// 3. 填充报表
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
// 4. 导出为PDF
JasperExportManager.exportReportToPdfFile(jasperPrint, "invoice_jasper.pdf");
System.out.println("JasperReports发票PDF生成成功!");
} catch (JRException e) {
e.printStackTrace();
}
}
}
💡 选择建议和注意事项
-
如何选择?
- 需要创建复杂布局和样式(如发票、合同)且预算充足 → 考虑 iText。
- 项目要求完全开源免费,或需处理现有PDF(如提取文本、合并拆分) → 选择 Apache PDFBox。
- 需生成数据驱动的、格式固定的报表(如每日销售报告、员工花名册) → 选择 JasperReports。
-
通用注意事项
- 中文支持:确保使用支持中文的字体(如SimSun、SimHei),并将字体文件嵌入PDF或在系统中可用,防止乱码。
- 布局精确性:发票对格式要求高,建议使用表格或绝对坐标来精确定位元素。
- 数据安全:涉及敏感信息的发票,应考虑使用库提供的功能对PDF进行加密或数字签名。
- 性能:大批量生成时,注意管理资源(如及时关闭文档流)。
- 模板化:对于发票这类格式固定的文档,强烈建议采用模板方式(如JasperReports或自行设计模板机制),将布局设计与代码分离,便于维护和修改。
希望这些详细的方案和代码示例能帮助你顺利实现发票导出PDF的功能。
878

被折叠的 条评论
为什么被折叠?



