1. 简介
Spring Boot 应用中整合 JasperReports,可实现 PDF、HTML、XML 格式报表的一键生成。通过引入 jasperreports 依赖,开发者能够利用其强大的模板引擎快速构建专业级报表。
- 首先,使用 Jaspersoft Studio 工具设计 .jrxml 格式的报表模板,定义数据字段、布局样式和分组统计等等逻辑;
- 在 Spring Boot 服务中加载并编译模板文件,结合 JDBC 或 Java 集合构建数据源,通过 JasperFillManager 填充数据生成 .jasper 报告对象;
- 调用 JasperExportManager 实现 PDF、HTML、XML 格式的导出。
2.实战案例
2.1 准备环境
首先,引入依赖
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>7.0.3</version>
</dependency>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports-pdf</artifactId>
<version>7.0.3</version>
</dependency>
配置字体
如果不进行相应的字体配置,那么默认是不支持中文(不报错,只是不显示)。在本篇文章中我们使用到的字体是 "黑体";所以,我们需要从C:\Windows\Fonts目录下将黑体字体复制到项目中,如下:
接下来,还需要定义fonts.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<fontFamilies>
<fontFamily name="黑体"><!--字体名称-->
<normal>fonts/simhei.ttf</normal><!--字体文件的路径-->
<bold>fonts/simhei.ttf</bold>
<italic>fonts/simhei.ttf</italic>
<boldItalic>fonts/simhei.ttf</boldItalic>
<pdfEncoding>Identity-H</pdfEncoding><!--这里的定义就与上面1.1的图设置相匹配了-->
<pdfEmbedded>true</pdfEmbedded>
<exportFonts>
<export key="net.sf.jasperreports.html">'黑体', Arial, Helvetica, sans-serif</export>
<export key="net.sf.jasperreports.xhtml">'黑体', Arial, Helvetica, sans-serif</export>
</exportFonts>
</fontFamily>
</fontFamilies>
最后,还需要如下的配置文件(resources目录下)
net.sf.jasperreports.extension.registry.factory.simple.font.families=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
net.sf.jasperreports.extension.simple.font.families.lobstertwo=fonts/fonts.xml
以上环境就准备完成了,接下来开始设计报表。
2.2 设计报表
首先,我们需要在如下地址下载设计工具:
https://community.jaspersoft.com/download-jaspersoft/community-edition/jaspersoft-studio_windows_7.x
打开工具后,设计如下的报表:
这些字体都设置为 "黑体"。接下来,还需要建立报表参数(如上$P)以及明显字段(如上$F)。
建立完上面的字段后,我们直接可以将其拖入到报表页面中。
最后,我们将设计好的报表user.jrxml放入项目中,如下:
2.3 导出报表
首先,加载报表并填充数据
public byte[] getReportData(List<User> users, String format) throws Exception {
System.err.println(users) ;
// 1.获取报表
ClassPathResource resource = new ClassPathResource("templates/user.jrxml") ;
JasperReport jasperReport = JasperCompileManager.compileReport(resource.getInputStream()) ;
// 2.设置数据 & 报表参数
JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(users) ;
Map<String, Object> parameters = new HashMap<>() ;
parameters.put("title", "用户列表") ;
// 3.填充报表
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
byte[] reportContent ;
try {
// 这里也可以直接导出HTML文件
switch (format) {
case "pdf" -> reportContent = JasperExportManager.exportReportToPdf(jasperPrint) ;
case "xml" -> reportContent = JasperExportManager.exportReportToXml(jasperPrint).getBytes() ;
case "html" -> {
String path = "f:/user.html" ;
JasperExportManager.exportReportToHtmlFile(jasperPrint, path) ;
reportContent = Files.readAllBytes(Paths.get(path)) ;
}
default -> throw new RuntimeException("未知报表格式") ;
}
} catch (JRException e) {
throw new RuntimeException(e) ;
}
return reportContent;
}
最后,我们定义Controller接口进行导出
@GetMapping("/export/{format}")
public ResponseEntity<Resource> getItemReport(@PathVariable String format) throws Exception {
// 1.模拟数据
List<User> list = new ArrayList<>() ;
for (int i = 0; i < 10; i++) {
list.add(new User(i + 0L, "姓名 - " + i, new Random().nextInt(100), i + "@qq.com", "地址 - " + i)) ;
}
// 2.获取填充后的报表数据
byte[] reportContent = getReportData(list, format) ;
// 3.下载文件
ByteArrayResource resource = new ByteArrayResource(reportContent);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.contentLength(resource.contentLength())
.header(HttpHeaders.CONTENT_DISPOSITION,
ContentDisposition.attachment()
.filename("user-report." + format)
.build().toString())
.body(resource);
}
2.4 测试
分别通过如下地址进行访问:
http://localhost:8080/users/export/pdf
http://localhost:8080/users/export/xml
http://localhost:8080/users/export/html