实现 PDF、HTML、XML 一键生成!

86 阅读3分钟

点击上方“程序员蜗牛g”,选择“设为星标”

跟蜗牛哥一起,每天进步一点点

程序员蜗牛g

大厂程序员一枚 跟蜗牛一起 每天进步一点点

33篇原创内容

**

公众号

本文将完整演示如何在 Spring Boot 项目中整合 JasperReports,从环境配置、模板设计到接口开发,逐步实现用户数据报表的导出。

集成 JasperReports 的整体步骤如下:

图片

项目目录结构

图片

引入依赖

在 pom.xml 中添加 JasperReports 相关依赖:

<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>

核心代码实现

 启动类

package com.icoderoad;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class SpringbootJasperreportApplication {    public static void main(String[] args) {        SpringApplication.run(SpringbootJasperreportApplication.class, args);    }}

User 实体类

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;    }}

报表生成工具类

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);        };    }}

控制层

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);    }}

配置文件

server:  port: 8080spring:  application:    name: springboot-jasperreport-demo

jasperreports.properties

net.sf.jasperreports.extension.registry.factory.simple.font.families=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactorynet.sf.jasperreports.extension.simple.font.families.simhei=fonts/fonts.xml

首先,在 Linux 系统中,将 Windows 的 黑体字体文件 simhei.ttf 拷贝到项目目录:

src/main/resources/fonts/simhei.ttf
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>    <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>

 user.jrxml 示例模板

<?xml version="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><![CDATA[$P{title}]]></text>            </staticText>        </band>    </title>
    <!-- 表头 -->    <columnHeader>        <band height="20">            <staticText><reportElement x="0" y="0" width="50" height="20"/><text><![CDATA[ID]]></text></staticText>            <staticText><reportElement x="50" y="0" width="100" height="20"/><text><![CDATA[姓名]]></text></staticText>            <staticText><reportElement x="150" y="0" width="50" height="20"/><text><![CDATA[年龄]]></text></staticText>            <staticText><reportElement x="200" y="0" width="150" height="20"/><text><![CDATA[邮箱]]></text></staticText>            <staticText><reportElement x="350" y="0" width="205" height="20"/><text><![CDATA[地址]]></text></staticText>        </band>    </columnHeader>
    <!-- 数据体 -->    <detail>        <band height="20">            <textField><reportElement x="0" y="0" width="50" height="20"/><textFieldExpression><![CDATA[$F{id}]]></textFieldExpression></textField>            <textField><reportElement x="50" y="0" width="100" height="20"/><textFieldExpression><![CDATA[$F{name}]]></textFieldExpression></textField>            <textField><reportElement x="150" y="0" width="50" height="20"/><textFieldExpression><![CDATA[$F{age}]]></textFieldExpression></textField>            <textField><reportElement x="200" y="0" width="150" height="20"/><textFieldExpression><![CDATA[$F{email}]]></textFieldExpression></textField>            <textField><reportElement x="350" y="0" width="205" height="20"/><textFieldExpression><![CDATA[$F{address}]]></textFieldExpression></textField>        </band>    </detail></jasperReport>

测试接口

启动服务后,分别访问以下地址即可获取不同格式的报表:

结论

通过本文的实践,我们基于 Spring Boot + JasperReports 搭建了一套完整的报表生成解决方案,实现了 PDF、HTML、XML 的多格式一键导出。整个过程涵盖了 依赖引入、字体配置、模板设计、数据填充、接口实现 等关键环节。

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!