当前位置: 代码网 > it编程>编程语言>Java > SpringBoot集成iText快速生成PDF教程

SpringBoot集成iText快速生成PDF教程

2025年11月25日 Java 我要评论
springboot集成itext 9.4.0生成pdf2025年itext已发展到9.x版本,本文将带你体验最新特性和最佳实践在现代企业应用开发中,动态生成pdf文档是一个常见需求。无论是生成报表、

springboot集成itext 9.4.0生成pdf

2025年itext已发展到9.x版本,本文将带你体验最新特性和最佳实践

在现代企业应用开发中,动态生成pdf文档是一个常见需求。无论是生成报表、发票、合同还是其他业务单据,pdf格式因其跨平台、保持布局不变的特性而备受青睐。

本文将详细介绍如何在springboot项目中集成itext 9.4.0——当前最新的版本,来实现高效、专业的pdf生成。

一、itext 9新特性与架构变革

itext 9.x相比旧版本进行了彻底的重构:

  • 模块化设计:按功能拆分为多个独立模块
  • 性能提升:底层架构优化,处理速度更快
  • api现代化:更符合现代java开发习惯
  • 功能增强:支持更多pdf标准和特性

二、环境准备与依赖配置

maven依赖配置

在springboot项目的pom.xml中添加以下依赖:

<properties>
    <itext.version>9.4.0</itext.version>
</properties>

<dependencies>
    <!-- itext 9 核心模块 -->
    <dependency>
        <groupid>com.itextpdf</groupid>
        <artifactid>kernel</artifactid>
        <version>${itext.version}</version>
    </dependency>
    <dependency>
        <groupid>com.itextpdf</groupid>
        <artifactid>io</artifactid>
        <version>${itext.version}</version>
    </dependency>
    <dependency>
        <groupid>com.itextpdf</groupid>
        <artifactid>layout</artifactid>
        <version>${itext.version}</version>
    </dependency>
    <dependency>
        <groupid>com.itextpdf</groupid>
        <artifactid>forms</artifactid>
        <version>${itext.version}</version>
    </dependency>
    <!-- 条形码支持 -->
    <dependency>
        <groupid>com.itextpdf</groupid>
        <artifactid>barcodes</artifactid>
        <version>${itext.version}</version>
    </dependency>
    <!-- 中文支持 -->
    <dependency>
        <groupid>com.itextpdf</groupid>
        <artifactid>font-asian</artifactid>
        <version>${itext.version}</version>
    </dependency>
</dependencies>

三、完整的service层实现

1. 基础pdf服务

@service
public class pdfservice {
    
    /**
     * 创建简单pdf文档
     */
    public void createsimplepdf(outputstream outputstream) throws ioexception {
        pdfwriter writer = new pdfwriter(outputstream);
        pdfdocument pdfdoc = new pdfdocument(writer);
        document document = new document(pdfdoc);
        
        // 添加内容
        document.add(new paragraph("hello, itext 9.4.0!")
            .setfontsize(20)
            .setbold());
        document.add(new paragraph("这是一个使用springboot和itext 9生成的pdf文档"));
        document.add(new paragraph("生成时间: " + new date()));
        
        // 关闭文档
        document.close();
    }
    
    /**
     * 创建带表格的pdf
     */
    public void createtablepdf(outputstream outputstream) throws ioexception {
        pdfwriter writer = new pdfwriter(outputstream);
        pdfdocument pdfdoc = new pdfdocument(writer);
        document document = new document(pdfdoc);
        
        // 创建3列表格
        table table = new table(3);
        
        // 添加表头
        table.addheadercell(new cell().add(new paragraph("姓名").setbold()));
        table.addheadercell(new cell().add(new paragraph("部门").setbold()));
        table.addheadercell(new cell().add(new paragraph("工资").setbold()));
        
        // 添加数据行
        table.addcell(new cell().add(new paragraph("张三")));
        table.addcell(new cell().add(new paragraph("技术部")));
        table.addcell(new cell().add(new paragraph("8000")));
        
        table.addcell(new cell().add(new paragraph("李四")));
        table.addcell(new cell().add(new paragraph("市场部")));
        table.addcell(new cell().add(new paragraph("7500")));
        
        table.addcell(new cell().add(new paragraph("王五")));
        table.addcell(new cell().add(new paragraph("财务部")));
        table.addcell(new cell().add(new paragraph("8200")));
        
        document.add(new paragraph("员工信息表").setfontsize(16).setbold());
        document.add(table);
        document.close();
    }
    
    /**
     * 生成带条形码的pdf
     */
    public void createpdfwithbarcode(outputstream outputstream, string barcodedata) throws ioexception {
        pdfwriter writer = new pdfwriter(outputstream);
        pdfdocument pdfdoc = new pdfdocument(writer);
        document document = new document(pdfdoc);
        
        // 添加标题
        document.add(new paragraph("条形码示例文档")
            .setfontsize(18)
            .setbold()
            .settextalignment(textalignment.center));
        
        // 添加条形码
        document.add(new paragraph("条形码数据: " + barcodedata));
        
        // 创建code 128条形码
        barcode128 barcode = new barcode128(pdfdoc);
        barcode.setcode(barcodedata);
        barcode.setfont(null); // 不显示文本
        
        // 将条形码转换为图像
        image barcodeimage = new image(barcode.createformxobject(pdfdoc))
            .setwidth(200)
            .setautoscaleheight(true);
        
        document.add(barcodeimage);
        document.close();
    }
    
    /**
     * 生成带图片和条形码的pdf
     */
    public void createpdfwithimageandbarcode(outputstream outputstream, string imageurl, string barcodedata) throws ioexception {
        pdfwriter writer = new pdfwriter(outputstream);
        pdfdocument pdfdoc = new pdfdocument(writer);
        document document = new document(pdfdoc);
        
        // 添加标题
        document.add(new paragraph("产品信息卡")
            .setfontsize(18)
            .setbold()
            .settextalignment(textalignment.center));
        
        // 添加图片(如果有)
        if (imageurl != null && !imageurl.trim().isempty()) {
            try {
                image image = new image(imagedatafactory.create(imageurl))
                    .setwidth(200)
                    .setautoscaleheight(true)
                    .sethorizontalalignment(horizontalalignment.center);
                document.add(image);
            } catch (exception e) {
                document.add(new paragraph("图片加载失败: " + e.getmessage()));
            }
        }
        
        // 添加条形码
        if (barcodedata != null && !barcodedata.trim().isempty()) {
            barcode128 barcode = new barcode128(pdfdoc);
            barcode.setcode(barcodedata);
            
            image barcodeimage = new image(barcode.createformxobject(pdfdoc))
                .setwidth(250)
                .setautoscaleheight(true)
                .sethorizontalalignment(horizontalalignment.center);
            
            document.add(new paragraph("产品条形码:").setbold());
            document.add(barcodeimage);
        }
        
        document.close();
    }
    
    /**
     * 创建报告pdf
     */
    public void createreportpdf(outputstream outputstream) throws ioexception {
        pdfwriter writer = new pdfwriter(outputstream);
        pdfdocument pdfdoc = new pdfdocument(writer);
        document document = new document(pdfdoc);
        
        // 报告标题
        document.add(new paragraph("月度销售报告")
            .setfontsize(24)
            .setbold()
            .settextalignment(textalignment.center));
        
        // 报告信息
        document.add(new paragraph("报告周期: " + new date()));
        document.add(new paragraph("生成部门: 销售部"));
        
        // 销售数据表格
        table salestable = new table(4);
        salestable.addheadercell(new cell().add(new paragraph("产品").setbold()));
        salestable.addheadercell(new cell().add(new paragraph("季度").setbold()));
        salestable.addheadercell(new cell().add(new paragraph("销售额").setbold()));
        salestable.addheadercell(new cell().add(new paragraph("增长率").setbold()));
        
        // 示例数据
        string[][] salesdata = {
            {"产品a", "q1", "¥120,000", "15%"},
            {"产品a", "q2", "¥138,000", "15%"},
            {"产品b", "q1", "¥85,000", "8%"},
            {"产品b", "q2", "¥92,000", "8%"}
        };
        
        for (string[] row : salesdata) {
            for (string cell : row) {
                salestable.addcell(new cell().add(new paragraph(cell)));
            }
        }
        
        document.add(salestable);
        document.close();
    }
    
    /**
     * 创建发票pdf
     */
    public void createinvoicepdf(outputstream outputstream) throws ioexception {
        pdfwriter writer = new pdfwriter(outputstream);
        pdfdocument pdfdoc = new pdfdocument(writer);
        document document = new document(pdfdoc);
        
        // 发票标题
        document.add(new paragraph("商业发票")
            .setfontsize(20)
            .setbold()
            .settextalignment(textalignment.center));
        
        // 发票信息表格
        table invoicetable = new table(2);
        invoicetable.addcell(new cell().add(new paragraph("发票号码:").setbold()));
        invoicetable.addcell(new cell().add(new paragraph("inv-2024-001")));
        invoicetable.addcell(new cell().add(new paragraph("开票日期:").setbold()));
        invoicetable.addcell(new cell().add(new paragraph(new date().tostring())));
        invoicetable.addcell(new cell().add(new paragraph("客户名称:").setbold()));
        invoicetable.addcell(new cell().add(new paragraph("某某科技有限公司")));
        
        document.add(invoicetable);
        
        // 商品明细表格
        table itemstable = new table(4);
        itemstable.addheadercell(new cell().add(new paragraph("商品名称").setbold()));
        itemstable.addheadercell(new cell().add(new paragraph("数量").setbold()));
        itemstable.addheadercell(new cell().add(new paragraph("单价").setbold()));
        itemstable.addheadercell(new cell().add(new paragraph("金额").setbold()));
        
        itemstable.addcell(new cell().add(new paragraph("笔记本电脑")));
        itemstable.addcell(new cell().add(new paragraph("2")));
        itemstable.addcell(new cell().add(new paragraph("¥5,999")));
        itemstable.addcell(new cell().add(new paragraph("¥11,998")));
        
        itemstable.addcell(new cell().add(new paragraph("无线鼠标")));
        itemstable.addcell(new cell().add(new paragraph("5")));
        itemstable.addcell(new cell().add(new paragraph("¥89")));
        itemstable.addcell(new cell().add(new paragraph("¥445")));
        
        document.add(new paragraph("商品明细:").setbold());
        document.add(itemstable);
        
        // 总计
        document.add(new paragraph("总计: ¥12,443").setbold().setfontsize(16));
        
        document.close();
    }
}

2. 中文pdf服务

@service
public class chinesepdfservice {
    
    /**
     * 创建支持中文的pdf文档
     */
    public void createchinesepdf(outputstream outputstream) throws ioexception {
        pdfwriter writer = new pdfwriter(outputstream);
        pdfdocument pdfdoc = new pdfdocument(writer);
        document document = new document(pdfdoc);
        
        // 使用中文字体
        pdffont chinesefont = pdffontfactory.createfont("stsong-light", "unigb-ucs2-h", true);
        
        // 添加中文内容
        document.add(new paragraph("中文pdf文档示例")
            .setfont(chinesefont)
            .setfontsize(20)
            .setbold()
            .settextalignment(textalignment.center));
        
        document.add(new paragraph("企业名称:某某科技有限公司")
            .setfont(chinesefont));
        
        document.add(new paragraph("公司地址:北京市海淀区中关村大街1号")
            .setfont(chinesefont));
        
        document.add(new paragraph("联系电话:010-12345678")
            .setfont(chinesefont));
        
        // 中文表格
        table table = new table(3);
        table.addheadercell(new cell().add(new paragraph("姓名").setfont(chinesefont).setbold()));
        table.addheadercell(new cell().add(new paragraph("职位").setfont(chinesefont).setbold()));
        table.addheadercell(new cell().add(new paragraph("部门").setfont(chinesefont).setbold()));
        
        table.addcell(new cell().add(new paragraph("张三").setfont(chinesefont)));
        table.addcell(new cell().add(new paragraph("软件工程师").setfont(chinesefont)));
        table.addcell(new cell().add(new paragraph("技术部").setfont(chinesefont)));
        
        table.addcell(new cell().add(new paragraph("李四").setfont(chinesefont)));
        table.addcell(new cell().add(new paragraph("产品经理").setfont(chinesefont)));
        table.addcell(new cell().add(new paragraph("产品部").setfont(chinesefont)));
        
        document.add(table);
        document.close();
    }
}

3. 模板pdf服务

@service
public class templatepdfservice {
    
    /**
     * 基于模板填充pdf表单
     */
    public void fillpdftemplate(outputstream outputstream, map<string, string> formdata) throws ioexception {
        // 创建临时模板(实际项目中应该从文件系统或数据库读取模板)
        byte[] templatebytes = createtemplatepdf();
        
        // 读取模板
        pdfreader reader = new pdfreader(new bytearrayinputstream(templatebytes));
        pdfwriter writer = new pdfwriter(outputstream);
        pdfdocument pdfdoc = new pdfdocument(reader, writer);
        
        // 获取表单
        pdfacroform form = pdfacroform.getacroform(pdfdoc, true);
        
        // 填充数据
        for (map.entry<string, string> entry : formdata.entryset()) {
            string fieldname = entry.getkey();
            string fieldvalue = entry.getvalue();
            pdfformfield field = form.getfield(fieldname);
            if (field != null) {
                field.setvalue(fieldvalue);
            }
        }
        
        // 扁平化表单(使字段不可编辑)
        form.flattenfields();
        
        pdfdoc.close();
    }
    
    /**
     * 创建示例模板pdf(实际项目中应使用现有的pdf模板)
     */
    private byte[] createtemplatepdf() throws ioexception {
        bytearrayoutputstream baos = new bytearrayoutputstream();
        pdfwriter writer = new pdfwriter(baos);
        pdfdocument pdfdoc = new pdfdocument(writer);
        
        // 创建表单
        pdfacroform form = pdfacroform.getacroform(pdfdoc, true);
        
        // 添加表单字段
        rectangle rect = new rectangle(100, 700, 200, 20);
        pdftextformfield namefield = pdftextformfield.createtext(pdfdoc, rect, "name", "");
        form.addfield(namefield);
        
        rect = new rectangle(100, 650, 200, 20);
        pdftextformfield emailfield = pdftextformfield.createtext(pdfdoc, rect, "email", "");
        form.addfield(emailfield);
        
        rect = new rectangle(100, 600, 200, 20);
        pdftextformfield phonefield = pdftextformfield.createtext(pdfdoc, rect, "phone", "");
        form.addfield(phonefield);
        
        // 添加标签
        document document = new document(pdfdoc);
        document.add(new paragraph("姓名:").setfixedposition(50, 700, 50));
        document.add(new paragraph("邮箱:").setfixedposition(50, 650, 50));
        document.add(new paragraph("电话:").setfixedposition(50, 600, 50));
        
        document.close();
        return baos.tobytearray();
    }
}

四、完整的pdf生成controller

@restcontroller
@requestmapping("/api/pdf")
@crossorigin(origins = "*")
public class pdfgeneratorcontroller {
    
    @autowired
    private pdfservice pdfservice;
    
    @autowired
    private chinesepdfservice chinesepdfservice;
    
    @autowired
    private templatepdfservice templatepdfservice;

    /**
     * 1. 基础pdf生成接口
     * 生成包含简单文本的pdf文档
     */
    @getmapping("/basic")
    public responseentity<byte[]> generatebasicpdf() {
        try {
            bytearrayoutputstream outputstream = new bytearrayoutputstream();
            pdfservice.createsimplepdf(outputstream);
            
            return responseentity.ok()
                .contenttype(mediatype.application_pdf)
                .header("content-disposition", "inline; filename=\"basic-document.pdf\"")
                .body(outputstream.tobytearray());
        } catch (ioexception e) {
            return responseentity.status(httpstatus.internal_server_error)
                .body(("pdf生成失败: " + e.getmessage()).getbytes());
        }
    }

    /**
     * 2. 中文pdf生成接口
     * 演示中文字体处理和中文内容支持
     */
    @getmapping("/chinese")
    public responseentity<byte[]> generatechinesepdf() {
        try {
            bytearrayoutputstream outputstream = new bytearrayoutputstream();
            chinesepdfservice.createchinesepdf(outputstream);
            
            return responseentity.ok()
                .contenttype(mediatype.application_pdf)
                .header("content-disposition", "inline; filename=\"chinese-document.pdf\"")
                .body(outputstream.tobytearray());
        } catch (ioexception e) {
            return responseentity.status(httpstatus.internal_server_error)
                .body(("中文pdf生成失败: " + e.getmessage()).getbytes());
        }
    }

    /**
     * 3. 表格pdf生成接口
     * 展示表格创建和数据展示功能
     */
    @getmapping("/table")
    public responseentity<byte[]> generatetablepdf() {
        try {
            bytearrayoutputstream outputstream = new bytearrayoutputstream();
            pdfservice.createtablepdf(outputstream);
            
            return responseentity.ok()
                .contenttype(mediatype.application_pdf)
                .header("content-disposition", "inline; filename=\"table-document.pdf\"")
                .body(outputstream.tobytearray());
        } catch (ioexception e) {
            return responseentity.status(httpstatus.internal_server_error)
                .body(("表格pdf生成失败: " + e.getmessage()).getbytes());
        }
    }

    /**
     * 4. 条形码pdf生成接口
     * 演示条形码生成功能(需要barcodes模块)
     */
    @postmapping("/barcode")
    public responseentity<byte[]> generatebarcodepdf(@requestparam string barcodedata) {
        try {
            bytearrayoutputstream outputstream = new bytearrayoutputstream();
            pdfservice.createpdfwithbarcode(outputstream, barcodedata);
            
            return responseentity.ok()
                .contenttype(mediatype.application_pdf)
                .header("content-disposition", "inline; filename=\"barcode-document.pdf\"")
                .body(outputstream.tobytearray());
        } catch (ioexception e) {
            return responseentity.status(httpstatus.internal_server_error)
                .body(("条形码pdf生成失败: " + e.getmessage()).getbytes());
        }
    }

    /**
     * 5. 图片pdf生成接口
     * 展示图片和条形码的混合文档
     */
    @postmapping("/image-barcode")
    public responseentity<byte[]> generateimagebarcodepdf(
            @requestparam(required = false) string imageurl,
            @requestparam string barcodedata) {
        try {
            bytearrayoutputstream outputstream = new bytearrayoutputstream();
            pdfservice.createpdfwithimageandbarcode(outputstream, imageurl, barcodedata);
            
            return responseentity.ok()
                .contenttype(mediatype.application_pdf)
                .header("content-disposition", "inline; filename=\"image-barcode-document.pdf\"")
                .body(outputstream.tobytearray());
        } catch (ioexception e) {
            return responseentity.status(httpstatus.internal_server_error)
                .body(("图片条形码pdf生成失败: " + e.getmessage()).getbytes());
        }
    }

    /**
     * 6. 模板pdf生成接口
     * 基于现有pdf模板填充数据
     */
    @postmapping("/template")
    public responseentity<byte[]> generatetemplatepdf(@requestbody map<string, string> formdata) {
        try {
            bytearrayoutputstream outputstream = new bytearrayoutputstream();
            templatepdfservice.fillpdftemplate(outputstream, formdata);
            
            return responseentity.ok()
                .contenttype(mediatype.application_pdf)
                .header("content-disposition", "inline; filename=\"template-document.pdf\"")
                .body(outputstream.tobytearray());
        } catch (ioexception e) {
            return responseentity.status(httpstatus.internal_server_error)
                .body(("模板pdf生成失败: " + e.getmessage()).getbytes());
        }
    }

    /**
     * 7. 报告pdf下载接口
     */
    @getmapping("/download/report")
    public responseentity<byte[]> downloadreportpdf() {
        try {
            bytearrayoutputstream outputstream = new bytearrayoutputstream();
            pdfservice.createreportpdf(outputstream);
            
            return responseentity.ok()
                .contenttype(mediatype.application_pdf)
                .header("content-disposition", "attachment; filename=\"sales-report.pdf\"")
                .body(outputstream.tobytearray());
        } catch (ioexception e) {
            return responseentity.status(httpstatus.internal_server_error)
                .body(("报告pdf下载失败: " + e.getmessage()).getbytes());
        }
    }

    /**
     * 8. 发票pdf下载接口
     */
    @getmapping("/download/invoice")
    public responseentity<byte[]> downloadinvoicepdf() {
        try {
            bytearrayoutputstream outputstream = new bytearrayoutputstream();
            pdfservice.createinvoicepdf(outputstream);
            
            return responseentity.ok()
                .contenttype(mediatype.application_pdf)
                .header("content-disposition", "attachment; filename=\"invoice.pdf\"")
                .body(outputstream.tobytearray());
        } catch (ioexception e) {
            return responseentity.status(httpstatus.internal_server_error)
                .body(("发票pdf下载失败: " + e.getmessage()).getbytes());
        }
    }
}

五、itext框架优劣分析

优势

  1. 功能全面:支持文本、表格、图片、条形码、表单等几乎所有pdf功能
  2. 性能优秀:处理大型文档时性能表现良好
  3. 标准兼容:完美支持pdf/a、pdf/ua等国际标准
  4. 文档完善:官方文档详细,社区活跃
  5. 企业级支持:提供商业许可证和技术支持

劣势

  1. 学习曲线:api较为复杂,新手需要时间适应
  2. 许可证限制:agpl协议对商业使用有限制
  3. 内存占用:处理大型文档时内存消耗较高
  4. 配置复杂:模块化设计增加了依赖管理的复杂度

六、不同版本差异对比

特性itext 5.xitext 7.x/9.x说明
架构设计单体架构模块化设计itext 9按功能拆分为多个jar
api设计传统api现代化apiitext 9 api更清晰一致
条形码支持内置核心独立模块itext 9需要单独引入barcodes
性能表现一般优化提升itext 9底层重构,性能更好
学习资源丰富相对较少itext 5教程更多,itext 9较新
维护状态维护模式积极开发itext 9是未来发展方向

七、版本选择建议

选择itext 5.x的情况

  • 维护遗留项目
  • 需要大量现有代码示例
  • 项目对性能要求不高
  • 快速原型开发

选择itext 7.x/9.x的情况

  • 新项目开发
  • 需要最佳性能
  • 长期维护考虑
  • 需要使用最新pdf标准特性

八、最佳实践总结

  1. 依赖管理:仔细选择所需模块,避免引入不必要的依赖
  2. 资源清理:使用try-with-resources确保pdf文档正确关闭
  3. 异常处理:妥善处理io异常和itext特定异常
  4. 内存管理:对于大文档,考虑分块处理和流式输出
  5. 字体优化:预加载和复用字体对象提升性能

总结

通过本文的完整示例和详细分析,你应该能够在springboot项目中顺利集成itext 9.4.0,并根据具体需求选择合适的版本和功能模块。

itext虽然有一定的学习成本,但其强大的功能和稳定性使其成为企业级pdf处理的优选方案。

itext官方文档https://itextpdf.com/

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com