2. Maven依赖
首先需要在pom.xml
中添加jasperreports
依赖:
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.20.0</version>
</dependency>
最新版本可在Maven仓库查询。
3. 报表模板
报表设计通过JRXML文件定义,这是JasperReports引擎可解析的特殊XML结构。我们重点关注与Java代码生成相关的核心结构。
以下是一个员工信息报表的简化示例:
<jasperReport ... >
<field name="FIRST_NAME" class="java.lang.String"/>
<field name="LAST_NAME" class="java.lang.String"/>
<field name="SALARY" class="java.lang.Double"/>
<field name="ID" class="java.lang.Integer"/>
<detail>
<band height="51" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{FIRST_NAME}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="100" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{LAST_NAME}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="200" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{SALARY}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
3.1. 编译报表
JRXML文件需先编译才能填充数据。使用JasperCompileManager
完成编译:
InputStream employeeReportStream
= getClass().getResourceAsStream("/employeeReport.jrxml");
JasperReport jasperReport
= JasperCompileManager.compileReport(employeeReportStream);
为避免重复编译,可保存为.jasper文件:
JRSaver.saveObject(jasperReport, "employeeReport.jasper");
4. 填充报表
最常用方式是通过数据库记录填充报表,需在报表中定义SQL查询。先修改报表添加查询语句:
<jasperReport ... >
<queryString>
<![CDATA[SELECT * FROM EMPLOYEE]]>
</queryString>
...
</jasperReport>
创建数据源:
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:employee-schema.sql")
.build();
}
填充报表:
JasperPrint jasperPrint = JasperFillManager.fillReport(
jasperReport, null, dataSource.getConnection());
⚠️ 第二个参数传null
,因为报表暂未使用参数。
4.1. 参数使用
参数适用于传递数据源中不存在或需动态调整的数据。可修改SQL查询或报表内容。先添加三个参数:
<jasperReport ... >
<parameter name="title" class="java.lang.String" />
<parameter name="minSalary" class="java.lang.Double" />
<parameter name="condition" class="java.lang.String">
<defaultValueExpression>
<![CDATA["1 = 1"]]></defaultValueExpression>
</parameter>
// ...
</jasperreport>
添加标题段显示title
参数:
<jasperreport ... >
// ...
<title>
<band height="20" splitType="Stretch">
<textField>
<reportElement x="238" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression class="java.lang.String">
<![CDATA[$P{title}]]></textFieldExpression>
</textField>
</band>
</title>
...
</jasperreport/>
修改查询使用参数:
SELECT * FROM EMPLOYEE
WHERE SALARY >= $P{minSalary} AND $P!{condition}
✅ 注意condition
参数使用$P!{}
语法,表示直接拼接SQL而非预编译参数。
准备参数并填充报表:
Map<String, Object> parameters = new HashMap<>();
parameters.put("title", "Employee Report");
parameters.put("minSalary", 15000.0);
parameters.put("condition", " LAST_NAME ='Smith' ORDER BY FIRST_NAME");
JasperPrint jasperPrint
= JasperFillManager.fillReport(..., parameters, ...);
❌ 参数名需与报表定义一致,缺失参数将使用defaultValueExpression
默认值。
5. 导出报表
导出步骤:
- 创建对应格式的Exporter对象
- 设置填充后的报表作为输入
- 指定输出位置
- 可选配置导出参数
5.1. PDF导出
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporter.setExporterOutput(
new SimpleOutputStreamExporterOutput("employeeReport.pdf"));
SimplePdfReportConfiguration reportConfig
= new SimplePdfReportConfiguration();
reportConfig.setSizePageToContent(true);
reportConfig.setForceLineBreakPolicy(false);
SimplePdfExporterConfiguration exportConfig
= new SimplePdfExporterConfiguration();
exportConfig.setMetadataAuthor("baeldung");
exportConfig.setEncrypted(true);
exportConfig.setAllowedPermissionsHint("PRINTING");
exporter.setConfiguration(reportConfig);
exporter.setConfiguration(exportConfig);
exporter.exportReport();
5.2. XLS导出
JRXlsxExporter exporter = new JRXlsxExporter();
// 设置输入输出...
SimpleXlsxReportConfiguration reportConfig
= new SimpleXlsxReportConfiguration();
reportConfig.setSheetNames(new String[] { "Employee Data" });
exporter.setConfiguration(reportConfig);
exporter.exportReport();
5.3. CSV导出
JRCsvExporter exporter = new JRCsvExporter();
// 设置输入...
exporter.setExporterOutput(
new SimpleWriterExporterOutput("employeeReport.csv"));
exporter.exportReport();
5.4. HTML导出
HtmlExporter exporter = new HtmlExporter();
// 设置输入...
exporter.setExporterOutput(
new SimpleHtmlExporterOutput("employeeReport.html"));
exporter.exportReport();
6. 子报表
子报表本质是嵌入到主报表中的标准报表。先创建员工邮箱子报表:
<jasperReport ... >
<parameter name="idEmployee" class="java.lang.Integer" />
<queryString>
<![CDATA[SELECT * FROM EMAIL WHERE ID_EMPLOYEE = $P{idEmployee}]]>
</queryString>
<field name="ADDRESS" class="java.lang.String"/>
<detail>
<band height="20" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="156" height="20"/>
<textElement/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{ADDRESS}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
修改主报表嵌入子报表:
<detail>
<band ... >
<subreport>
<reportElement x="0" y="20" width="300" height="27"/>
<subreportParameter name="idEmployee">
<subreportParameterExpression>
<![CDATA[$F{ID}]]></subreportParameterExpression>
</subreportParameter>
<connectionExpression>
<![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
<subreportExpression class="java.lang.String">
<![CDATA["employeeEmailReport.jasper"]]></subreportExpression>
</subreport>
</band>
</detail>
✅ 通过编译后的.jasper文件引用子报表,并传递idEmployee
参数和数据库连接。
编译两个报表:
InputStream employeeReportStream
= getClass().getResourceAsStream("/employeeReport.jrxml");
JasperReport jasperReport
= JasperCompileManager.compileReport(employeeReportStream);
JRSaver.saveObject(jasperReport, "employeeReport.jasper");
InputStream emailReportStream
= getClass().getResourceAsStream("/employeeEmailReport.jrxml");
JRSaver.saveObject(
JasperCompileManager.compileReport(emailReportStream),
"employeeEmailReport.jasper");
填充和导出代码无需修改。
7. 总结
本文简要介绍了JasperReports核心功能:
- 编译报表并填充数据库记录
- 通过参数动态控制报表内容
- 嵌入子报表
- 导出多种格式(PDF/XLS/CSV/HTML)
完整代码示例见GitHub仓库。