Java案例如何生成PDF文件?

wen java案例 70

本文目录导读:

Java案例如何生成PDF文件?

  1. 主流方案对比
  2. iText实现案例(最常用方案)
  3. Apache PDFBox实现案例
  4. JasperReports报表生成(适合复杂报表)
  5. 最佳实践建议

在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最专业。

抱歉,评论功能暂时关闭!