当前位置:

首页 > 编程开发 > SpringBoot使用JasperReports报表引擎的原理与使用实践

SpringBoot使用JasperReports报表引擎的原理与使用实践

本文目录

    JasperReports是Java生态中流行的开源报表引擎,支持PDF、Excel、Word等格式输出。通过JRXML模板实现数据与样式分离,编译后运行时填充数据生成报表。在SpringBoot中集成,利用JasperFillManager填充数据源,JasperExportManager导出文档,实现高效报表生成。

    在Ja va报表领域,JasperReports是一个绕不开的名字。下面从几个方面来深入解析,看看它到底是什么、怎么用,以及如何在实际项目中落地。

    一、JasperReports 是什么

    1.1 定位

    JasperReports 是 Ja va 生态中最流行的开源报表引擎,专门用于生成格式化的文档(PDF、Excel、Word、HTML、CSV 等)。它的核心价值是将数据和模板分离,通过模板定义报表样式,运行时填充数据后生成最终文档。

    SpringBoot使用JasperReports报表引擎的原理与使用实践

    1.2 类比理解

    Word 邮件合并:
      模板(.docx)+ 数据(Excel联系人) → 批量生成信件
    
    JasperReports:
      模板(.jrxml/.jasper)+ 数据(数据库/Ja va对象) → 批量生成 PDF/Excel/HTML
    

    1.3 典型应用场景

    场景示例
    发货单打印选中订单 → 生成 PDF 发货单(含条码/表格/签章)
    财务报表月度销售汇总 → 导出 Excel
    物流面单快递单/运单 → 生成固定格式 PDF 批量打印
    库存盘点表仓库商品清单 → 导出打印
    对账单供应商对账 → 生成 PDF 发送邮件

    二、核心概念

    2.1 关键术语

    概念说明文件格式
    JRXML报表模板源文件,XML 格式,定义报表布局和样式.jrxml
    Jasper编译后的模板文件(二进制),运行时直接加载.jasper
    JasperPrint填充数据后的内存报表对象,可导出为各种格式内存对象
    DataSource数据源,为报表提供数据(JDBC/Ja va集合/JSON等)-
    Parameter报表参数,从外部传入的变量(如标题、日期、Logo等)-
    Field数据字段,对应数据源中每条记录的列-
    Band报表区域/带区(页眉/列头/明细/页脚/汇总等)-

    2.2 报表结构

    ┌─────────────────────────────────────────┐
    │          Title Band(标题区)             │  ← 整个报表只出现一次
    ├─────────────────────────────────────────┤
    │        Page Header(页眉)               │  ← 每页顶部
    ├─────────────────────────────────────────┤
    │       Column Header(列标题)            │  ← 表格列名
    ├─────────────────────────────────────────┤
    │         Detail Band(明细区)            │  ← 每条数据重复一次
    │    ┌────┬──────┬────┬──────┬─────┐     │
    │    │序号│ 商品名 │数量│  单价  │ 金额 │     │
    │    ├────┼──────┼────┼──────┼─────┤     │
    │    │ 1  │冰箱   │ 2  │3999  │7998 │     │
    │    │ 2  │洗衣机 │ 1  │2999  │2999 │     │
    │    │... │...   │... │...   │...  │     │
    │    └────┴──────┴────┴──────┴─────┘     │
    ├─────────────────────────────────────────┤
    │        Column Footer(列汇总)           │  ← 合计行
    ├─────────────────────────────────────────┤
    │        Page Footer(页脚)               │  ← 每页底部(页码等)
    ├─────────────────────────────────────────┤
    │         Summary(总汇总)                │  ← 整个报表最后
    └─────────────────────────────────────────┘
    

    三、工作流程

    3.1 完整生命周期

    设计阶段(开发时):
      Jaspersoft Studio 设计模板 → 保存为 .jrxml 文件
           │
           ▼
      编译模板:JasperCompileManager.compileReport() → .jasper 文件
           │
           ▼(部署到项目 resources 目录)
    
    运行阶段(运行时):
      加载 .jasper 模板
           │
           ▼
      填充数据:JasperFillManager.fillReport(模板, 参数, 数据源) → JasperPrint
           │
           ▼
      导出文档:JasperExportManager.exportReportToPdf(jasperPrint) → PDF/Excel/HTML
           │
           ▼
      返回给前端下载/预览/打印
    

    3.2 运行时数据流

    Controller 接收请求(如:打印发货单)
      │
      ├─→ Service 查询数据库获取发货单数据
      │     └── List 数据集
      │
      ├─→ 组装参数 Map(标题、公司名、打印日期等)
      │
      ├─→ 创建数据源 JRBeanCollectionDataSource(数据集)
      │
      ├─→ 加载模板 .jasper(从 classpath 或数据库)
      │
      ├─→ JasperFillManager.fillReport(模板, 参数, 数据源)
      │     └── → JasperPrint(内存中的完整报表)
      │
      ├─→ 导出为目标格式
      │     ├── PDF:JasperExportManager.exportReportToPdfStream()
      │     ├── Excel:JRXlsxExporter
      │     ├── Word:JRDocxExporter
      │     └── HTML:HtmlExporter
      │
      └─→ 写入 HttpServletResponse 输出流
           └── 前端收到文件下载/预览
    

    四、涉及的技术知识点

    4.1 模板设计

    知识点说明
    Jaspersoft StudioEclipse 插件形式的可视化模板设计器(拖拽式)
    JRXML 语法XML 格式的模板描述语言
    表达式语言$F{fieldName}(字段)、$P{paramName}(参数)、$V{varName}(变量)
    子报表(Subreport)报表嵌套,主报表中嵌入子报表
    条件样式根据数据值动态改变颜色/字体/可见性
    条码/二维码内置 Barcode4J 支持各种条码格式
    图表内置 JFreeChart 支持柱状图/折线图/饼图

    4.2 数据源类型

    数据源类场景
    Ja va Bean 集合JRBeanCollectionDataSource最常用,传入 List
    JDBC 直连JRResultSetDataSource直接执行 SQL
    空数据源JREmptyDataSource只有参数没有明细数据
    Map 集合JRMapCollectionDataSourceList数据
    JSONJsonDataSourceJSON 字符串/文件

    4.3 导出格式

    格式导出器类用途
    PDFJasperExportManager打印、归档
    Excel (xlsx)JRXlsxExporter数据分析
    Word (docx)JRDocxExporter文档编辑
    HTMLHtmlExporter在线预览
    CSVJRCsvExporter数据交换
    图片 (PNG)JRGraphics2DExporter缩略图

    4.4 设计模式

    模式应用
    模板方法编译 → 填充 → 导出的固定流程
    策略模式不同 Exporter 实现不同格式导出
    建造者模式ExporterInput/OutputItem 的构建
    工厂模式JasperCompileManager/JasperFillManager 工厂方法

    五、通用示例代码

    5.1 pom.xml 依赖

    
        
        
            net.sf.jasperreports
            jasperreports
            6.20.0
        
        
        
            net.sf.jasperreports
            jasperreports-fonts
            6.20.0
        
        
        
            org.apache.poi
            poi-ooxml
            5.2.3
        
    

    5.2 JRXML 模板示例(发货单)

    
    
        
        
        
        
        
        
        
        
        
        
        
        
        
            
                
            
        
        
        
            <band height="80">
                <staticText>
                    <reportElement x="0" y="0" width="555" height="30"/>
                    <textElement textAlignment="Center">
                        <font size="18" isBold="true" fontName="华文宋体"/>
                    </textElement>
                    <text><![CDATA[发 货 单]]></text>
                </staticText>
                <textField>
                    <reportElement x="0" y="40" width="200" height="20"/>
                    <textFieldExpression><![CDATA["单号:" + $P{deliveryCode}]]></textFieldExpression>
                </textField>
                <textField>
                    <reportElement x="355" y="40" width="200" height="20"/>
                    <textFieldExpression><![CDATA["日期:" + $P{printDate}]]></textFieldExpression>
                </textField>
            </band>
        
        
        
            
                
                    
                    
                
                
                    
                    
                
                
                    
                    
                
                
                    
                    
                
            
        
        
        
            
                
                    
                    
                
                
                    
                    
                
                
                    
                    
                
                
                    
                    
                
            
        
        
        
            
                
                    
                    
                        
                    
                    
                
            
        
    

    5.3 JasperUtil 工具类封装

    package com.example.utils;
    
    import ja va.io.ByteArrayOutputStream;
    import ja va.io.InputStream;
    import ja va.util.List;
    import ja va.util.Map;
    import ja vax.servlet.http.HttpServletResponse;
    import net.sf.jasperreports.engine.*;
    import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
    import net.sf.jasperreports.engine.export.ooxml.JRDocxExporter;
    import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter;
    import net.sf.jasperreports.export.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * JasperReports 报表工具类.
     * 封装编译、填充、导出的完整流程.
     */
    public class JasperUtil {
    
        private static final Logger log = LoggerFactory.getLogger(JasperUtil.class);
    
        /**
         * 导出类型枚举.
         */
        public enum DocType {
            PDF, EXCEL, WORD, HTML
        }
    
        /**
         * 生成报表并写入 HTTP 响应(文件下载).
         *
         * @param templatePath 模板路径(classpath 下的 .jasper 文件)
         * @param params       报表参数
         * @param dataList     数据集合(对应模板中的 Field)
         * @param fileName     下载文件名
         * @param docType      导出格式
         * @param response     HTTP 响应
         */
        public static  void exportToResponse(
                String templatePath,
                Map params,
                List dataList,
                String fileName,
                DocType docType,
                HttpServletResponse response) {
    
            try {
                byte[] bytes = generateReport(templatePath, params, dataList, docType);
    
                // 设置响应头
                String contentType;
                String extension;
                switch (docType) {
                    case PDF:
                        contentType = "application/pdf";
                        extension = ".pdf";
                        break;
                    case EXCEL:
                        contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                        extension = ".xlsx";
                        break;
                    case WORD:
                        contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
                        extension = ".docx";
                        break;
                    default:
                        contentType = "text/html";
                        extension = ".html";
                }
    
                response.setContentType(contentType);
                response.setHeader("Content-Disposition",
                    "attachment; filename=" + ja va.net.URLEncoder.encode(fileName + extension, "UTF-8"));
                response.setContentLength(bytes.length);
                response.getOutputStream().write(bytes);
                response.getOutputStream().flush();
    
            } catch (Exception e) {
                log.error("报表导出失败", e);
                throw new RuntimeException("报表导出失败", e);
            }
        }
    
        /**
         * 生成报表字节数组.
         */
        public static  byte[] generateReport(
                String templatePath,
                Map params,
                List dataList,
                DocType docType) throws Exception {
    
            // 1. 加载编译好的模板
            InputStream templateStream = JasperUtil.class.getClassLoader()
                .getResourceAsStream(templatePath);
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(templateStream);
    
            // 2. 创建数据源
            JRDataSource dataSource;
            if (dataList != null && !dataList.isEmpty()) {
                dataSource = new JRBeanCollectionDataSource(dataList);
            } else {
                dataSource = new JREmptyDataSource();
            }
    
            // 3. 填充数据 → 生成 JasperPrint
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, dataSource);
    
            // 4. 导出为目标格式
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            switch (docType) {
                case PDF:
                    JasperExportManager.exportReportToPdfStream(jasperPrint, outputStream);
                    break;
                case EXCEL:
                    exportToExcel(jasperPrint, outputStream);
                    break;
                case WORD:
                    exportToWord(jasperPrint, outputStream);
                    break;
                default:
                    JasperExportManager.exportReportToHtmlFile(jasperPrint, outputStream.toString());
            }
            return outputStream.toByteArray();
        }
    
        private static void exportToExcel(JasperPrint jasperPrint, ByteArrayOutputStream out) throws Exception {
            JRXlsxExporter exporter = new JRXlsxExporter();
            exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
            exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(out));
            SimpleXlsxReportConfiguration config = new SimpleXlsxReportConfiguration();
            config.setOnePagePerSheet(false);
            config.setDetectCellType(true);
            exporter.setConfiguration(config);
            exporter.exportReport();
        }
    
        private static void exportToWord(JasperPrint jasperPrint, ByteArrayOutputStream out) throws Exception {
            JRDocxExporter exporter = new JRDocxExporter();
            exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
            exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(out));
            exporter.exportReport();
        }
    }
    

    5.4 业务代码使用示例

    @RestController
    public class DeliveryPrintController {
    
        @Resource
        private DeliveryService deliveryService;
    
        /**
         * 打印发货单(导出PDF).
         */
        @GetMapping("/api/delivery/print")
        public void printDeliveryOrder(
                @RequestParam Integer deliveryId,
                HttpServletResponse response) {
    
            // 1. 查询发货单数据
            DeliveryOrderDto order = deliveryService.getDeliveryOrder(deliveryId);
            List items = deliveryService.getDeliveryItems(deliveryId);
    
            // 2. 组装报表参数
            Map params = new HashMap<>();
            params.put("companyName", "xxx科技");
            params.put("deliveryCode", order.getDeliveryCode());
            params.put("printDate", DateUtil.formatStandardDate(new Date()));
            params.put("customerName", order.getCustomerName());
            params.put("address", order.getShipToAddress());
    
            // 3. 导出 PDF
            JasperUtil.exportToResponse(
                "print/delivery_order.jasper",  // classpath 下的模板
                params,
                items,                           // 明细数据
                "发货单_" + order.getDeliveryCode(),
                JasperUtil.DocType.PDF,
                response);
        }
    
        /**
         * 批量打印(多个发货单合并为一个PDF).
         */
        @PostMapping("/api/delivery/batch-print")
        public void batchPrint(
                @RequestBody List deliveryIds,
                HttpServletResponse response) {
    
            List prints = new ArrayList<>();
            for (Integer id : deliveryIds) {
                DeliveryOrderDto order = deliveryService.getDeliveryOrder(id);
                List items = deliveryService.getDeliveryItems(id);
    
                Map params = new HashMap<>();
                params.put("deliveryCode", order.getDeliveryCode());
                // ... 其他参数
    
                // 生成每个发货单的 JasperPrint
                InputStream template = getClass().getClassLoader()
                    .getResourceAsStream("print/delivery_order.jasper");
                JasperReport report = (JasperReport) JRLoader.loadObject(template);
                JasperPrint print = JasperFillManager.fillReport(report, params,
                    new JRBeanCollectionDataSource(items));
                prints.add(print);
            }
    
            // 合并导出为一个 PDF
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", "attachment; filename=batch_delivery.pdf");
            JRPdfExporter exporter = new JRPdfExporter();
            exporter.setExporterInput(SimpleExporterInput.getInstance(prints));
            exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(response.getOutputStream()));
            exporter.exportReport();
        }
    }
    

    5.5 模板 DTO 示例

    /**
     * 发货单明细DTO(字段名需与JRXML中的Field名称一致).
     */
    @Data
    public class DeliveryItemDto {
        private String productCode;    // 对应 $F{productCode}
        private String productName;    // 对应 $F{productName}
        private Integer quantity;      // 对应 $F{quantity}
        private BigDecimal price;      // 对应 $F{price}
    }
    

    六、开发流程

    6.1 模板设计(使用 Jaspersoft Studio)

    1. 下载安装 Jaspersoft Studio(免费,基于 Eclipse)
    2. 新建 Jasper Report → 选择模板尺寸(A4/自定义)
    3. 拖拽组件到 Band 中:
       - Static Text:固定文本
       - Text Field:动态字段 $F{xxx}
       - Image:图片/Logo
       - Barcode:条码
       - Line/Rectangle:线条/边框
    4. 定义 Parameters(外部传入的参数)
    5. 定义 Fields(对应数据源的字段)
    6. 预览效果 → 保存为 .jrxml
    7. 编译为 .jasper → 放到项目 resources/print/ 目录
    

    6.2 项目中的文件组织

    src/main/resources/
    ├── print/
    │   ├── delivery_order.jrxml      ← 模板源文件(用于修改)
    │   ├── delivery_order.jasper     ← 编译后模板(运行时加载)
    │   ├── outbound_order.jasper     ← 出库单模板
    │   └── stock_report.jasper       ← 库存报表模板
    ├── font/
    │   └── simsun.ttf                ← 中文字体文件
    └── jasperreports.properties       ← JasperReports 配置

    七、关键设计总结

    设计要点实现方式收益
    数据与模板分离.jasper 模板 + List 数据修改样式不改代码,修改逻辑不改模板
    预编译模板.jrxml → .jasper(开发时编译)运行时直接加载,无需编译开销
    多格式输出同一模板导出 PDF/Excel/Word/HTML一次设计,多种输出
    批量合并多个 JasperPrint 合并为一个 PDF批量打印只需下载一个文件
    中文支持嵌入字体文件到项目中避免服务器字体缺失导致中文乱码
    参数化$P{paramName} 动态传入同一模板适配不同场景(换标题/Logo/签章)
    子报表嵌套Subreport 组件主从报表(如订单主信息 + 商品明细)
    表达式计算$V{variable} + calculation=Sum自动计算合计/平均/计数
    本文内容来源于网友投稿,如有侵权请联系删除。
    作者最新文章
    编程开发
    相关文章 更多
    解决PHP递归报错:max_nesting_level限制与内存溢出处理
    解决PHP递归报错:max_nesting_level限制与内存溢出处理

    遇到PHP递归报错时,不要盲目调大max_nesting_level。本文教你区分Xdebug限制、内存耗尽和正则递归错误,提供代码级的终止条件优化与迭代替代方案,彻底解决栈溢出问题。

    PHP递归中static变量与引用传递的常见陷阱及调试
    PHP递归中static变量与引用传递的常见陷阱及调试

    本文分析PHP递归中static变量导致的状态污染及引用传递引发的共享数据修改问题。提供具体的代码复现、缓存键设计建议及调试打印技巧,帮助开发者避免隐蔽的逻辑错误。

    PHP递归性能优化技巧与迭代替代方案
    PHP递归性能优化技巧与迭代替代方案

    解析PHP递归函数在树形数据处理中的性能瓶颈,提供预加载数据消除I/O、使用显式栈替代深层递归的实战方案,帮助开发者在代码可读性与执行效率间做出合理取舍。

    Java测试中怎么使用Mockito模拟依赖对象
    Java测试中怎么使用Mockito模拟依赖对象

    详细讲解在Java单元测试中如何使用Mockito模拟依赖对象,包括引入依赖、创建Mock、打桩返回值、行为验证以及Mock与Spy的核心差异和常见陷阱排查。

    链表删除节点的时间复杂度是多少及其详细分析
    链表删除节点的时间复杂度是多少及其详细分析

    详细分析链表删除节点的时间复杂度,深入探讨单链表与双向链表在不同已知前提下的查找与删除开销,并结合完整代码与清晰图解进行对比总结。

    codex如何配置模型参数及文件设置教程
    codex如何配置模型参数及文件设置教程

    想知道如何让AI写出的代码更贴合你的习惯?本文手把手教你在VS Code中调整Codex相关模型参数,通过修改配置文件优化温度值和令牌限制,解决代码建议不准确或响应慢的问题。

    Claude Code AI编程工具实力揭秘与编程助手实测
    Claude Code AI编程工具实力揭秘与编程助手实测

    通过实测展示Claude Code在终端中如何理解自然语言指令、自动修改代码文件并处理复杂编程任务,帮助开发者评估其实际辅助能力。

    winforms教程自学入门与基础开发步骤详解
    winforms教程自学入门与基础开发步骤详解

    本教程详细讲解如何使用Visual Studio创建WinForms项目,通过添加按钮和标签控件并编写点击事件代码,实现一个基础的计数器功能,适合C#初学者快速上手Windows窗体应用开发。

    Cursor自动补全设置教程教你快速开启代码补全功能
    Cursor自动补全设置教程教你快速开启代码补全功能

    详解Cursor编辑器中自动补全功能的开启与优化设置,涵盖Tab触发机制、上下文窗口调整及模型切换,帮助开发者解决补全延迟、干扰大等问题,提升编码流畅度。

    pandas的数据格式怎么转换和设置方法教程
    pandas的数据格式怎么转换和设置方法教程

    详解Pandas中数据格式转换的核心方法,包括astype强制转换、to_numeric容错处理及日期解析技巧,解决常见类型错误并提升数据处理效率。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    macOS软件
    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    Mac软件 更多
    photoshop
    photoshop
    Windows、macOS 、 iPad

    Photoshop 2026 是 Adobe 推出的专业图像处理与视觉设计软件,支持 Windows、macOS 和 iPad 等平台,广泛应用于摄影修图、电商设计、平面海报、数字绘画及视觉合成等创作场景。

    Blender
    Blender
    Windows、macOS 和 Linux

    Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

    灵活计算器
    灵活计算器
    macOS/iOS/Android

    灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

    WINDOWS 更多
    3dmax(3ds max)
    3dmax(3ds max)
    Windows

    Autodesk 3ds Max 是一款专业的三维建模、动画与渲染软件,广泛应用于建筑可视化、游戏开发、影视动画、广告设计和产品展示等领域。

    photoshop
    photoshop
    Windows、macOS 、 iPad

    Photoshop 2026 是 Adobe 推出的专业图像处理与视觉设计软件,支持 Windows、macOS 和 iPad 等平台,广泛应用于摄影修图、电商设计、平面海报、数字绘画及视觉合成等创作场景。

    Blender
    Blender
    Windows、macOS 和 Linux

    Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。