Springboot 整合 ireporter 实践

news2025/1/13 3:36:18

背景

这段时间,在做项目时,设计到需要带参数的批量生成报告。尝试了很多方法,包括grafana等BI工具。虽然grafana这种BI工具可以在线查看,但是无法导出。甚至当想把报告整合邮件发送时,grafana就显得无能为力了。于是在搜索了各个工具后发现了 ireporter 。不得不说,现在这个时代,我们遇到的无法解决研发场景,肯定有人也遇到了,并且已经有了很好的解决方案。

ireporter支持实现编辑好报告模板,然后通过sql查询和参数控制,实现报告的在线生成。并提供导出pdf和html的格式,支持报告生成后直接访问和下载。或作为邮件的附件,直接发送,解决了我的场景。

废话不多说,直接上代码。

事前准备

在整合之前,你需要提前准备好 ireporter 的模板文件。ireporter的下载安装,网上有很多教程,此处就不再赘述,可自行搜索相关内容。

模板准备步骤:

  1. 安装好软件之后,打开软件,配置一个简单的报告模板,并保存。

  2. 右键项目名称,选择【compile report】编译报告。
    在这里插入图片描述

  3. 将【*.jasper】模板文件放到项目工程下
    在这里插入图片描述

整合 spring boot 工程

maven引用

<!--https://mvnrepository.com/artifact/com.itextpdf/itext-asian-->
<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>6.17.0</version>
</dependency>
<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports-fonts</artifactId>
    <version>6.17.0</version>
</dependency>
<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>iTextAsian</artifactId>
    <version>5.2.0.2</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/iTextAsian_5.2.0.2.jar</systemPath>
</dependency>
<dependency>
    <groupId>net.sf.barcode4j</groupId>
    <artifactId>barcode4j</artifactId>
    <version>2.1</version>
</dependency>
<dependency>
    <groupId>net.sourceforge.barbecue</groupId>
    <artifactId>barbecue</artifactId>
    <version>1.5-beta1</version>
</dependency>
<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>batik-bridge</artifactId>
    <version>1.14</version>
</dependency>

数据连接

ireporter在生成报表时,需要读取数据库数据,因此需要一个数据库连接。此处为了说明,简单创建了一个数据库连接。实际项目中,需要对该工具类做适当的封装。

public class ConnectionProvider {  
  
    // 数据库连接信息,这里由于我的模板使用的是运营中心数据库,这里默认用研发云查询库数据库作为数据源
    // 实际项目中,需要对此部分配置信息进行封装
    private static String driverClassName ="com.mysql.jdbc.Driver";  
    private static String username="username";  
    private static String password="password";  
    private static String url="jdbc:mysql://ip:port/databaseName?useSSL=false";  
  
    static{  
        try {  
            Class.forName(driverClassName);  
        } catch (ClassNotFoundException e) {  
            throw new RuntimeException(e);  
        }  
    }  
    public static Connection getConnection(){  
        try {  
            return DriverManager.getConnection(url, username, password);  
        } catch (SQLException e) {  
            throw new RuntimeException(e);  
        }  
    }  
}

编写工具类

编写工具类,调用ireporter报告模板,生成相应的报告。

@Component  
public class JasperReporterHandle {  
  
    private static final Logger LOGGER = LoggerFactory.getLogger(JasperReporterHandle.class);  
  
    /**  
     * 导出报表为 pdf  
     * @param templateName ireporter工具生成的模板名称,使用全路径  
     * @param params 报告模板中定义的参数列表  
     * @param filePath 导出的pdf文件名称,使用全路径。实际开发中,此参数可省略,直接返回文件流,共页面直接下载。  
     */  
    public void processReporter2PDF(String templateName, Map<String, Object> params, String filePath) {  
  
        //1.读取模板文件  
        Resource resource = new ClassPathResource(templateName);  
  
        FileInputStream fis = null;  
        FileOutputStream fileOutputStream = null;  
  
        // 2. 获取数据库连接  
        Connection connection = ConnectionProvider.getConnection();  
  
        try {  
  
            fis = new FileInputStream(resource.getFile());  
            //2.模板和数据整合  
            JasperPrint jasperPrint = JasperFillManager  
                    .fillReport(fis, params, connection);  
  
            //3.导出PDF  
            File outFile = new File(filePath);  
            // 文件不存在,且创建失败,则直接返回  
            if (!outFile.exists() && !outFile.createNewFile()) {  
                LOGGER.error("file create failed. ");  
                return;            }  
            fileOutputStream = new FileOutputStream(outFile);  
            JasperExportManager.exportReportToPdfStream(jasperPrint, fileOutputStream);  
  
        } catch (JRException | IOException e) {  
            e.printStackTrace();  
        } finally {  
            // 关闭文件流  
            if (fileOutputStream != null) {  
                try {  
                    fileOutputStream.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
            if (fis != null) {  
                try {  
                    fis.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  
  
  
    /**  
     * 导出报表为 pdf  
     * @param templateName ireporter工具生成的模板名称,使用全路径  
     * @param params 报告模板中定义的参数列表  
     * @param fileName 导出的html文件名称,使用全路径。  
     */  
    public void processReporter2Html(String templateName, Map<String, Object> params, String fileName) {  
  
        // 1. 获取模板  
        Resource resource = new ClassPathResource(templateName);  
        FileInputStream fis = null;  
  
        // 2. 获取数据库连接  
        Connection connection = ConnectionProvider.getConnection();  
  
        try {  
            fis = new FileInputStream(resource.getFile());  
  
            // 3. 获取报告对象  
            JasperPrint jasperPrint = JasperFillManager.fillReport(fis, params, connection);  
  
            // 4. 导出至html文件  
            JasperExportManager.exportReportToHtmlFile(jasperPrint, fileName);  
        } catch (IOException | JRException e) {  
            e.printStackTrace();  
        }  
        finally {  
            if (fis != null) {  
                try {  
                    fis.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  
}

Service层

@Service  
public class JasperReporterServiceImpl implements JasperReporterService {  
  
    @Autowired  
    private JasperReporterHandle jasperReporterHandle;  
  
    // todo 换成自己的路径
    private static final String FILE_PATH = "C:/temp/jsreporter/";  
  
    public void processReport2PDF(Map<String, Object> param, String fileName) {  
  
        // 模板名称  
        String templateName = "static/data_center_billing_mail.jasper";  
  
        String fileFullPath = FILE_PATH + fileName;  
  
        jasperReporterHandle.processReporter2PDF(templateName, param, fileFullPath);  
  
    }  
  
    @Override  
    public void processReport2Html(Map<String, Object> param, String fileName) {  
  
        // 模板名称  
        String templateName = "static/data_center_billing_mail.jasper";  
  
        String outFileName = FILE_PATH + fileName;  
  
        jasperReporterHandle.processReporter2Html(templateName, param, outFileName);  
    }  
}

controller 层

@Controller  
@RequestMapping(value = "/test")  
public class TestController {  
  
  
    @Autowired  
    private JasperReporterService jasperReporterService;  
  
    @GetMapping("processReport2PDF/{projectId}")  
    @ResponseBody  
    public String processReport2PDF(@PathVariable("projectId") Integer projectId){  
  
        Map<String, Object> param = new HashMap<>();  
        param.put("projectId", projectId);  
  
        jasperReporterService.processReport2PDF(param, "resource-reporter-by-project.pdf");  
        return "OK";  
    }  
  
    @GetMapping("/processReport2Html/{projectId}")  
    @ResponseBody  
    public String processReport2Html(@PathVariable("projectId") Integer projectId) {  
  
        Map<String, Object> param = new HashMap<>();  
        param.put("projectId", projectId);  
  
        jasperReporterService.processReport2Html(param, "resource-reporter-by-project.html");  
  
        return "OK";  
    }  
  
}

测试

  1. 启动服务,浏览器访问地址。

在这里插入图片描述
2. 查看生成的文件
在这里插入图片描述

resource-reporter-by-project.html_files中存放的是表格对应的图片。

访问生成的html文件如下图。
在这里插入图片描述

结语

使用ireporter的一个缺点是,模板文件需要提前准备,虽然可以通过提供上传页面来支持,但是导致的结果是需要在两个页面之间切换。如果只是少数几个人使用,可以保持这种模式没问题。如果使用的人数较多,可以考虑对ireporter进行二次开发,提供在线模式,并将生成的模板放到云服务器上。这样其他应用可以直接读取云服务上的模板文件,而免去在应用之间的跳转。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/94363.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Sql Server 占用内存高,不释放内存问题处理记录(腾讯电脑管家小火箭清内存)

问题&#xff1a; 本人仓库管理系统厂家&#xff0c;项目上反应生产线箱码不能上传到我们系统&#xff0c;我们的WMS软件退出后重新登录也一直登录失败&#xff0c;并且服务器上数据库占用内存过高&#xff0c;SSMS数据库连接不上。 好家伙SQL Server占用了34个G内存。 接口…

前端基础(十二)_overflow属性、clear属性、vertical-align属性

overflow属性 overflow的第一个属性值是x轴方向的属性&#xff0c;第二个值是y周方向的属性 <style>.box1 {width: 150px;height: 50px;等价于下面两个属性/* overflow: hidden auto; */overflow-x: hidden;overflow-y: auto;}</style>1、overflow-x 只包含水平方…

VS2019编译QT6源码

现在QT在线安装只有QT6.2以上的版本和QT5.15&#xff0c;其他版本就需要自己编译&#xff0c;本文讲解在vs2019环境下编译qt6.1.3源码。 1 编译准备 从清华大学镜像站&#xff0c;下载源码&#xff0c;地址如下&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/qt/archive/…

【C++】继承/多态/文件

文章目录一、继承1 继承中的对象模型2 继承中构造和析构顺序3 继承中同名属性和函数处理方式&#xff08;隐藏&#xff09;4 继承同名静态成员属性和函数处理方式5 多继承语法6 菱形继承&#xff08;虚继承&#xff09;二、多态1 多态的原理剖析&#xff08;虚函数表指针&#…

【OpenSourceC#】JEngine框架

前言 一个完全依赖ILRuntime的框架&#xff0c;集成好了ILRuntime和AB资源热更&#xff0c;想用ILRuntime的可以很方便使用。 对着作者的文档JEngine看看框架功能都是怎么实现的。 看下文档中提到的功能如下 JEngine框架核心 热更资源工具 AssetMgr&#xff0c;框架集成…

询盘回复流程及外贸11步流程

询盘回复流程&#xff1a; 从事外贸的新手经常在网上寻找各种各样的外贸干货知识。其实&#xff0c;你不仅要关注某个环节的小细节&#xff0c;还要有“宏观”的思维。分过程、分步骤地梳理外贸工作&#xff0c;是外贸工作中十分重要的一个环节。今天&#xff0c;按照一般的回…

点云中点法向量,点拟合的直线,点拟合的平面

点云中点法向量 计算步骤&#xff1a; 找到点pi相邻点集合S所有点Vi,然后去中心化,并构造协方差矩阵,公式如下: 二维点云该点曲率计算方法&#xff1a; 三维点云该点曲率计算方法&#xff1a; 最小特征值对应的特征向量就是点的法向量 Eigen::Vector2d ComputeNormal(std::v…

m基于BP神经网络的房屋价值变换趋势预测matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 住宅价格是住宅市场的核心&#xff0c;住宅市场的变化关系到广大消费者的切身利益&#xff0c;商品房价格是升是降&#xff0c;销售是冷是旺&#xff0c;是社会关注的热点问题。因此&#xff0c;…

Mybatis-Plus 入门

文章目录0. 前言1. 相关概念1.1 名称介绍1.2 官网特性介绍2. 快速入门2.1 准备工作2.2.1 准备表2.2.2 创建工程2.2 入门测试2.2.1 编写实体类2.2.2 编写Mapper2.2.3 编写测试类3. CRUD3.1 条件构造器3.1.1 AbstractWrapper&#xff08;1&#xff09; 基本比较操作&#xff08;2…

想做数码管显示,单片机IO口资源不够?看看WTV890语音芯片能做些啥

在开发许多产品时许多工程师都会遇到以下问题&#xff0c;如&#xff1a;想驱动4位或10位的LED数码管显示&#xff0c;但是单片机的IO口不够用&#xff1b;要么更换IO口资源更多的MCU来控制&#xff0c;要么更换脚位丰富的单片机&#xff0c;这无疑在MCU上&#xff0c;加了1元左…

在Linux中使用at和crontab命令在指定时间计划任务服务程序

经验丰富的系统运维工程师可以使得Linux在无需人为介入的情况下&#xff0c;在指定的时间段自动启用或停止某些服务或命令&#xff0c;从而实现运维的自动化。尽管我们现在已经有了功能彪悍的脚本程序来执行一些批处理工作&#xff0c;但是&#xff0c;如果仍然需要在每天凌晨两…

2023年电气,电子与信息工程国际会议(ISEEIE 2023)

2023年电气&#xff0c;电子与信息工程国际会议&#xff08;ISEEIE 2023&#xff09; 重要信息 会议网址&#xff1a;www.iseeie.org 会议时间&#xff1a;2023年2月24-26日 召开地点&#xff1a;新加坡 截稿时间&#xff1a;2022年12月31日 录用通知&#xff1a;投稿后2周…

Mac如何做才能彻底清理垃圾

Mac磁盘空间又爆满了&#xff1f;系统运行又卡了&#xff1f;你的Mac需要清理内存缓存垃圾啦&#xff01;本文教会你如何彻底清除Mac垃圾文件&#xff0c;释放存储空间。 现在&#xff0c;Mac电脑最顶配的硬盘可达2TB。这么大的容量&#xff0c;应该够用了吧&#xff1f;可真正…

windowsserver2016安装

vmware安装windowsserver2016: 开始安装OpcServer服务器端&#xff1a; DOM配置过程&#xff1a; 1.设置OpcServer和OpcClient相同的administrator账号和密码 administrator、wong123 2.关闭OpcServer和OpcClient的防火墙 3.开启OpcServer和OpcClient远程桌面访问 4.OpcServe…

玩以太坊链上项目的必备技能(OOP-合约继承-Solidity之旅九)

继承 我们今天不讲别的&#xff0c;就只讲合约继承相关的内容。&#xff08;您是不是感觉这话挺眼熟的&#xff0c;没错&#xff0c;您确实看过&#xff0c;前一篇开头便是今天我们不讲三国&#xff0c;来讲讲 流程控制&#xff0c;您会觉得我上头了还是怎么&#xff01;&…

Java-数据库范式与表关系

数据库范式 数据库范式简介 什么是范式&#xff08;NF NormalForm&#xff09; ● 范式是符合某一种设计要求的总结 在数据库中表的设计&#xff0c;必须保证其合理性 ● 数据库表的设计关系整个系统的架构&#xff0c;关系到后续的开发效率和运行效率 如何设计合理的数据库…

【leetcode】二叉树的最近公共祖先

一、题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也…

在职位招聘数据处理中使用Loess回归曲线以及分箱、回归、聚类方法 检查离群点及光滑数据【数据挖掘机器学习】

文章目录一.需求分析二.使用局部回归&#xff08;Loess&#xff09;曲线&#xff08;增加一条光滑曲线到散布图&#xff09;方法处理数据三.使用分箱、回归、聚类方法 检查离群点及光滑数据&#xff1b;一.需求分析 本文主题&#xff1a;使用局部回归&#xff08;Loess&#x…

Jmeter(十九):nmon性能系统监控工具

一、Nmon介绍 Nmon得名于 Nigel 的监控器&#xff0c;是IBM的员工 Nigel Griffiths 为 AIX 和 Linux 系统开发的&#xff0c;使用 Nmon 可以很轻松的监控系统的CPU、内存、网络、硬盘、文件系统、NFS、高耗进程、资源和 IBM Power 系统的微分区的信息 Nmon是一款计算机性能系…

【JavaEE】HTTP + HTTPS(Part2 )

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录【HTTP响应详解】1. 认识状态码2.认识响应“报头”header3.认识响应“正文”body【通过 Java socket 构造 HTTP 请求】三、HTTPS四、Tomcat&#xff1a;http服务器THINK一个人最大的痛苦来源于对自己无能的愤怒。 【…