AB
AiBoss站
教程

Jasper

教程

JasperReports 快速入门:用 Jaspersoft Studio 设计模板并在 Java 中导出 PDF/HTML

从零跑通第一个 JasperReports 报表:用 Jaspersoft Studio 建项目、认识 band 分区、添加参数与字段、编译 .jrxml,再在 Java 里填充数据并导出 PDF 或 HTML。

JasperReports 是一个用 Java 编写的开源报表引擎,它可以从多种数据源读取数据,生成像素级可控的文档,并支持查看、打印以及导出为 HTML、PDF、Excel、Word 等格式。当项目需要一套可以随客户需求快速调整的报表时,把报表结构放在模板文件里、把数据交给代码填充,是一种常见做法。这篇教程面向第一次接触 JasperReports 的 Java 开发者,目标是走完一条最小但完整的链路:设计模板、编译模板、在代码里填充数据、把结果输出成 PDF 或 HTML。模板的可视化设计借助 Jaspersoft Studio 完成,站内也整理了 Jasper 相关的工具信息,可以先了解整体定位再动手。

准备工作

开始之前需要把两样东西准备好:一个用来画模板的设计器,以及一个能跑 Java 的项目。

  • Jaspersoft Studio:报表模板的可视化设计工具,用来产出 .jrxml 文件。下载时选择 Jaspersoft Studio CE 版本,安装过程按默认选项一路下一步即可,不需要额外配置。
  • JDK 与构建工具:因为最终要在 Java 代码里调用模板,所以需要一个可用的 JDK,以及 Maven 或同类依赖管理工具。
  • JasperReports 依赖:在项目的 pom.xml 中加入报表引擎的 jar 包依赖。素材中使用的坐标如下,版本号请以官网当前发布的信息为准,不要照抄旧版本:
<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>6.9.0</version>
</dependency>

这里有一个容易混淆的点需要先分清:.jrxml 是设计器产出的、可读可编辑的模板源文件;.jasper 是它编译之后的二进制文件,代码运行时加载的是后者。两者要成对管理,模板改动后必须重新编译。

操作步骤

第一步:在设计器里创建项目

打开 Jaspersoft Studio,通过 File -> New -> Project 新建一个项目,项目名可以填 demo。项目是模板文件的容器,后续生成的 .jrxml 和 .jasper 都会放在里面,便于统一管理。

第二步:新建报表模板

在项目上右键选择 New -> Jasper Report,也可以走菜单 File -> New -> Jasper Report。向导里选择竖向 A4 纸大小的模板。到了 Data Adapter 这一步,选择 One Empty Record,也就是空数据源——这一步只是为了让设计器能完成创建,真正的数据稍后由 Java 代码传入。完成后就得到了第一个模板文件,默认名为 Blank_A4.jrxml。

第三步:理解模板的分区结构

模板设计区被横向切分成若干个 band,每个 band 决定了一段内容在什么位置、以什么频率出现。这些 band 都可以右键删除,也可以按需新增。理解它们是读懂模板的关键:

Band作用与打印时机
Title标题区,数据有多页时只在第一页打印
Page Header页头区,多页情况下每页都会打印
Column Header列头区,配合 Detail 区打印列表数据,多页情况下每页都会打印
Detail明细区,可以新增多个,组合打印出多组列表数据,多页情况下每页都会打印
Column Footer列表底部区,多页情况下每页都会打印
Page Footer页底部区,多页情况下每页都会打印
Summary合计区,只在最后一页打印

记住一条规律:凡是带 Page 字样的区域每页重复,Detail 区按数据行重复,Summary 只在结尾出现一次。后面放元素时,放错 band 就会出现「每页都重复」或「只出现一次」这类不符合预期的效果。

第四步:往模板里添加元素

元素从右侧的 Basic Elements 面板拖拽到设计区。拖进去之后可以任意调整大小和位置,双击元素即可修改它显示的内容;选中元素后,右侧属性面板可以设置边框、字体、字号、文本对齐方式等。

  1. 从 Basic Elements 拖一个 Static Text 到 Title 区,双击改成报表标题。
  2. 在左侧 Outline 面板的 Parameters 上右键 Create Parameter,新建一个参数,命名为 name,类型选 java.lang.String。参数适合承载「整份报表只有一个值」的信息,比如打印人、报表标题、查询条件。
  3. 把 name 参数拖到 Page Header 区,同样在右侧调整它的显示属性。
  4. 在 Outline 面板的 Fields 上右键 Create Field,新建两个字段 Field1、Field2,类型都选 java.lang.String。字段对应的是数据源里的列,会被逐行填充。
  5. 把 Field1、Field2 拖到 Detail1 区。拖拽时设计器会自动在 Column Header 区带出两个值为 Field1、Field2 的 Static Text 元素作为列头,把它们的位置和下面的字段对齐。
  6. 点击预览查看样式。此时还没有给 Field1、Field2 对应的数据集赋值,所以预览里这两列显示为 null,这是正常现象,不代表模板有问题。

第五步:编译模板

在左侧 Project Explorer 中,于 Blank_A4.jrxml 上右键选择 Compile Report,会生成编译后的 Blank_A4.jasper。这一步不能跳过:Java 代码加载的是 .jasper,如果只改了 .jrxml 而没有重新编译,运行时用的仍是旧模板。

第六步:把编译产物放进项目资源目录

把上一步生成的 Blank_A4.jasper 复制到 Java 项目的资源目录中。素材中的做法是按业务分目录存放,例如放在名为 chapter1 的目录下,代码里再通过工具方法定位到该目录。这样多个报表模板可以按章节或模块分开管理,不会全部堆在一个文件夹里。

第七步:在 Java 中填充数据并导出

下面这段控制器代码演示了完整的调用方式:构造参数 Map、构造数据列表、定位模板文件、按请求的格式导出。

@GetMapping("/jasper")
public void getReport(@RequestParam("type") String reportType,
                      HttpServletResponse response) throws Exception {

    HashMap<String, Object> parameters = new HashMap<String, Object>();
    parameters.put("name", "xiao ming");

    List<HashMap> list = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        HashMap<String, String> item = new HashMap<String, String>();
        item.put("Field1", "Field1-" + i);
        item.put("Field2", "Field2-" + i);
        list.add(item);
    }

    String jasperPath = JasperReportUtil.getJasperFileDir("chapter1");

    if (reportType.equals("pdf")) {
        JasperReportUtil.exportToPdf(jasperPath, parameters, list, response);
    } else if (reportType.equals("html")) {
        JasperReportUtil.exportToHtml(jasperPath, parameters, list, response);
    }
}

这段代码里有几个对应关系值得留意:

  • parameters 这个 Map 的 key 必须和模板里定义的参数名一致,这里放进去的 name 正好对应第四步创建的 name 参数,它会显示在 Page Header 区。
  • list 中每个 Map 的 key 必须和模板里定义的字段名一致,Field1、Field2 对应 Detail 区的两个字段。循环 100 次就得到 100 行明细。
  • 参数是整份报表共用一份,字段是每行一份,两者不要混用。
  • 导出格式由请求参数 type 决定,代码里分别走 PDF 和 HTML 两条分支。

把项目运行起来,在浏览器中访问对应地址并带上 type 参数,就能看到 HTML 或 PDF 格式的报表输出。

一个完整示例

把上面的步骤串起来,一个最小可运行的报表应用是这样构成的:

  1. 在 Jaspersoft Studio 中新建项目 demo,再新建一个竖向 A4 模板,Data Adapter 选 One Empty Record。
  2. 在 Title 区放一个 Static Text 作为标题;在 Page Header 区放参数 name;在 Detail1 区放字段 Field1、Field2,并在 Column Header 区对齐两个列头。
  3. 右键 Blank_A4.jrxml 执行 Compile Report,得到 Blank_A4.jasper。
  4. 把 Blank_A4.jasper 复制到项目的资源目录,例如 chapter1 下。
  5. 在 pom.xml 中加入 net.sf.jasperreports:jasperreports 依赖。
  6. 编写一个控制器方法:参数 Map 里放 name,数据列表里放 100 条带 Field1、Field2 的记录,通过工具类定位模板路径,再按 type 分别导出 PDF 或 HTML。
  7. 启动项目,访问接口并传入 type=pdf 或 type=html,检查输出结果:页头应显示 xiao ming,明细区应出现 100 行 Field1-0 到 Field1-99 的数据。

如果输出里明细为空、页头没有值,优先检查三件事:模板是否重新编译过、Map 的 key 是否与模板中的参数名和字段名完全一致、.jasper 文件是否确实被放进了代码能读到的资源路径。

注意事项

  • 模板改动必须重新编译。 .jrxml 只是源文件,运行时加载的是 .jasper。只改源文件不编译,页面上的效果不会变化,这是最常见的排查盲点。
  • 命名必须严格对应。 参数名、字段名与 Java 代码里 Map 的 key 是大小写敏感的字符串匹配,写错一个字母就会得到 null 而不是报错,排查起来比较费时。
  • band 决定重复频率。 元素放在 Page Header 会每页重复,放在 Title 只在第一页出现,放在 Summary 只在最后一页出现。位置放错会直接改变报表的版面结构。
  • Detail 区可以有多组。 需要同时打印多组列表数据时,可以新增多个 Detail 区组合使用,而不是把所有字段挤进同一个区域。
  • 依赖版本以官网为准。 报表引擎的版本迭代较快,不同版本对 JDK 和导出格式的支持范围可能不同,引入依赖前请核对官网当前发布的版本与兼容性说明。
  • 导出格式的可用性。 HTML、PDF、Excel、Word 等格式的支持情况与具体版本有关,实际项目中以当前版本实测结果为准。
  • 数据量较大的场景。 示例中一次性构造了 100 条记录,真实业务里数据往往来自数据库查询,需要考虑分页、内存占用以及导出大文件时的响应方式。