SpringBoot集成JasperReports实现PDF、HTML、XML的一键生成
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">核心原理</a></li><li><a href="#_label1">集成JasperReports步骤</a></li><li><a href="#_label2">项目目录结构</a></li><li><a href="#_label3">引入依赖</a></li><li><a href="#_label4">核心代码实现</a></li><li><a href="#_label5">测试接口</a></li><li><a href="#_label6">结论</a></li></ul></div><p style="text-align:center">JasperReports 是一个基于 Java 的开源报表工具,支持多种输出格式(如 PDF、HTML、XML 等),广泛应用于 Java 开发中生成动态报表‌。本文将完整演示如何在 Spring Boot 项目中整合 JasperReports,从环境配置、模板设计到接口开发,逐步实现用户数据报表的导出。</p><p class="maodian"><a name="_label0"></a></p><h2>核心原理</h2>
<ul><li><p>‌<strong>工作流程</strong>‌</p>
<ul><li>‌<strong>JRXML</strong>‌:XML 格式的报表模板文件,通过设计器(如 Jaspersoft Studio)创建‌。</li><li>‌<strong>Jasper</strong>‌:编译 JRXML 生成的二进制文件,用于数据填充‌。</li><li>‌<strong>Jrprint</strong>‌:填充数据后的报表对象,最终通过导出器生成目标格式文件‌。</li></ul></li><li><p>‌<strong>技术特点</strong>‌</p>
<ul><li>支持多种数据源(JDBC、JavaBeans、XML 等)‌。</li><li>可生成带水印的报表和子报表。</li></ul></li></ul>
<p class="maodian"><a name="_label1"></a></p><h2>集成JasperReports步骤</h2>
<p style="text-align:center"></p>
<p style="text-align:center"><img alt="实现 PDF、HTML、XML 一键生成!_xml_02" src="https://img.jbzj.com/file_images/article/202510/202510031050026.webp" width="632" /></p>
<p></p>
<p class="maodian"><a name="_label2"></a></p><h2>项目目录结构</h2>
<p style="text-align:center"></p>
<p style="text-align:center"><img alt="实现 PDF、HTML、XML 一键生成!_java_03" src="https://img.jbzj.com/file_images/article/202510/202510031050027.webp" width="520" /></p>
<p></p>
<p class="maodian"><a name="_label3"></a></p><h2>引入依赖</h2>
<p>在 <code>pom.xml</code> 中添加 JasperReports 相关依赖:</p>
<div class="jb51code"><pre class="brush:java;"><dependencies>
<!-- JasperReports 核心依赖 -->
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>7.0.3</version>
</dependency>
<!-- JasperReports PDF 支持 -->
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports-pdf</artifactId>
<version>7.0.3</version>
</dependency>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Lombok 简化实体类代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies></pre></div>
<p class="maodian"><a name="_label4"></a></p><h2>核心代码实现</h2>
<p> 启动类</p>
<div class="jb51code"><pre class="brush:java;">package com.icoderoad;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootJasperreportApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootJasperreportApplication.class, args);
}
}</pre></div>
<p>User 实体类</p>
<div class="jb51code"><pre class="brush:java;">package com.icoderoad.entity;
public class User {
private Long id;
private String name;
private Integer age;
private String email;
private String address;
public User(Long id, String name, Integer age, String email, String address) {
this.id = id;
this.name = name;
this.age = age;
this.email = email;
this.address = address;
}
public User() {}
// Getter 和 Setter
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}</pre></div>
<p>报表生成工具类</p>
<div class="jb51code"><pre class="brush:java;">package com.icoderoad.report;
import com.icoderoad.entity.User;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.springframework.core.io.ClassPathResource;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
public class ReportGenerator {
public static byte[] generate(List<User> users, String format) throws Exception {
// 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", "用户列表");
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
// 3. 导出不同格式
return switch (format) {
case "pdf" -> JasperExportManager.exportReportToPdf(jasperPrint);
case "xml" -> JasperExportManager.exportReportToXml(jasperPrint).getBytes();
case "html" -> {
String path = "/tmp/user.html";
JasperExportManager.exportReportToHtmlFile(jasperPrint, path);
yield Files.readAllBytes(Paths.get(path));
}
default -> throw new IllegalArgumentException("不支持的格式: " + format);
};
}
}</pre></div>
<p>控制层</p>
<div class="jb51code"><pre class="brush:java;">package com.icoderoad.controller;
import com.icoderoad.entity.User;
import com.icoderoad.report.ReportGenerator;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("/users")
public class ReportController {
@GetMapping("/export/{format}")
public ResponseEntity<Resource> export(@PathVariable String format) throws Exception {
// 模拟数据
List<User> users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
users.add(new User((long) i, "姓名-" + i, new Random().nextInt(100),
i + "@qq.com", "地址-" + i));
}
// 生成报表
byte[] content = ReportGenerator.generate(users, format);
ByteArrayResource resource = new ByteArrayResource(content);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.header(HttpHeaders.CONTENT_DISPOSITION,
ContentDisposition.attachment()
.filename("user-report." + format)
.build().toString())
.contentLength(resource.contentLength())
.body(resource);
}
}</pre></div>
<p>配置文件</p>
<div class="jb51code"><pre class="brush:java;">server:
port: 8080
spring:
application:
name: springboot-jasperreport-demo</pre></div>
<p><code>jasperreports.properties</code></p>
<div class="jb51code"><pre class="brush:java;">net.sf.jasperreports.extension.registry.factory.simple.font.families=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
net.sf.jasperreports.extension.simple.font.families.simhei=fonts/fonts.xml</pre></div>
<p>首先,在 Linux 系统中,将 Windows 的 <strong>黑体</strong>字体文件 <code>simhei.ttf</code> 拷贝到项目目录:</p>
<div class="jb51code"><pre class="brush:java;">src/main/resources/fonts/simhei.ttf</pre></div>
<div class="jb51code"><pre class="brush:java;">fonts/fonts.xml</pre></div>
<div class="jb51code"><pre class="brush:java;"><?xml versinotallow="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>
<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></pre></div>
<p> user.jrxml 示例模板</p>
<div class="jb51code"><pre class="brush:java;"><?xml versinotallow="1.0" encoding="UTF-8"?>
<!-- 用户列表报表模板 -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports
http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
name="user_report"
pageWidth="595" pageHeight="842"
columnWidth="555" leftMargin="20" rightMargin="20"
topMargin="20" bottomMargin="20" uuid="123e4567-e89b-12d3-a456-426614174000">
<!-- 报表参数 -->
<parameter name="title" class="java.lang.String"/>
<!-- 字段定义 -->
<field name="id" class="java.lang.Long"/>
<field name="name" class="java.lang.String"/>
<field name="age" class="java.lang.Integer"/>
<field name="email" class="java.lang.String"/>
<field name="address" class="java.lang.String"/>
<!-- 报表标题 -->
<title>
<band height="50">
<staticText>
<reportElement x="0" y="10" width="555" height="30"/>
<textElement textAlignment="Center">
<font fontName="黑体" size="16" isBold="true"/>
</textElement>
<text><!]></text>
</staticText>
</band>
</title>
<!-- 表头 -->
<columnHeader>
<band height="20">
<staticText><reportElement x="0" y="0" width="50" height="20"/><text><!]></text></staticText>
<staticText><reportElement x="50" y="0" width="100" height="20"/><text><!]></text></staticText>
<staticText><reportElement x="150" y="0" width="50" height="20"/><text><!]></text></staticText>
<staticText><reportElement x="200" y="0" width="150" height="20"/><text><!]></text></staticText>
<staticText><reportElement x="350" y="0" width="205" height="20"/><text><!]></text></staticText>
</band>
</columnHeader>
<!-- 数据体 -->
<detail>
<band height="20">
<textField><reportElement x="0" y="0" width="50" height="20"/><textFieldExpression><!]></textFieldExpression></textField>
<textField><reportElement x="50" y="0" width="100" height="20"/><textFieldExpression><!]></textFieldExpression></textField>
<textField><reportElement x="150" y="0" width="50" height="20"/><textFieldExpression><!]></textFieldExpression></textField>
<textField><reportElement x="200" y="0" width="150" height="20"/><textFieldExpression><!]></textFieldExpression></textField>
<textField><reportElement x="350" y="0" width="205" height="20"/><textFieldExpression><!]></textFieldExpression></textField>
</band>
</detail>
</jasperReport></pre></div>
<p class="maodian"><a name="_label5"></a></p><h2>测试接口</h2>
<p>启动服务后,分别访问以下地址即可获取不同格式的报表:</p>
<ul><li>PDF 报表:http://localhost:8080/users/export/pdf</li><li>XML 报表:http://localhost:8080/users/export/xml</li><li>HTML 报表:http://localhost:8080/users/export/html</li></ul>
<p class="maodian"><a name="_label6"></a></p><h2>结论</h2>
<p>通过本文的实践,我们基于 <strong>Spring Boot + JasperReports</strong> 搭建了一套完整的报表生成解决方案,实现了 <strong>PDF、HTML、XML</strong> 的多格式一键导出。整个过程涵盖了 <strong>依赖引入、字体配置、模板设计、数据填充、接口实现</strong> 等关键环节。</p>
頁:
[1]