
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 面板拖拽到设计区。拖进去之后可以任意调整大小和位置,双击元素即可修改它显示的内容;选中元素后,右侧属性面板可以设置边框、字体、字号、文本对齐方式等。
- 从 Basic Elements 拖一个 Static Text 到 Title 区,双击改成报表标题。
- 在左侧 Outline 面板的 Parameters 上右键
Create Parameter,新建一个参数,命名为name,类型选java.lang.String。参数适合承载「整份报表只有一个值」的信息,比如打印人、报表标题、查询条件。 - 把
name参数拖到 Page Header 区,同样在右侧调整它的显示属性。 - 在 Outline 面板的 Fields 上右键
Create Field,新建两个字段Field1、Field2,类型都选java.lang.String。字段对应的是数据源里的列,会被逐行填充。 - 把
Field1、Field2拖到 Detail1 区。拖拽时设计器会自动在 Column Header 区带出两个值为Field1、Field2的 Static Text 元素作为列头,把它们的位置和下面的字段对齐。 - 点击预览查看样式。此时还没有给
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 格式的报表输出。
一个完整示例
把上面的步骤串起来,一个最小可运行的报表应用是这样构成的:
- 在 Jaspersoft Studio 中新建项目
demo,再新建一个竖向 A4 模板,Data Adapter 选One Empty Record。 - 在 Title 区放一个 Static Text 作为标题;在 Page Header 区放参数
name;在 Detail1 区放字段Field1、Field2,并在 Column Header 区对齐两个列头。 - 右键
Blank_A4.jrxml执行Compile Report,得到Blank_A4.jasper。 - 把
Blank_A4.jasper复制到项目的资源目录,例如chapter1下。 - 在
pom.xml中加入net.sf.jasperreports:jasperreports依赖。 - 编写一个控制器方法:参数 Map 里放
name,数据列表里放 100 条带Field1、Field2的记录,通过工具类定位模板路径,再按type分别导出 PDF 或 HTML。 - 启动项目,访问接口并传入
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 条记录,真实业务里数据往往来自数据库查询,需要考虑分页、内存占用以及导出大文件时的响应方式。