如何利用Spring已配置的dataSource创建JRDataSource用于Jasper报表打印?
用Spring配置的DataSource生成JRDataSource的几种方法
嘿,这个问题我太熟悉了!既然你已经在Spring配置类里搞定了DataSource,那把它转换成Jasper报表需要的JRDataSource其实没什么难度,给你分享两种最常用的方案:
方案1:直接用Jasper的JdbcDataSource包装Spring DataSource
这是最省心的方式,Jasper自带的JdbcDataSource可以直接接收标准的JDBC DataSource,完美适配你已经配置好的Spring DataSource。
代码示例
首先在你的服务类里注入Spring的DataSource:
import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.data.JdbcDataSource; import javax.sql.DataSource; import org.springframework.stereotype.Service; @Service public class JasperReportService { private final DataSource springDataSource; // 推荐用构造注入(Spring 4.3+支持),比@Autowired更稳妥 public JasperReportService(DataSource springDataSource) { this.springDataSource = springDataSource; } public void generateReport() throws JRException { // 1. 把Spring DataSource包装成Jasper的JdbcDataSource JdbcDataSource jrDataSource = new JdbcDataSource(); jrDataSource.setDataSource(springDataSource); // 2. 填充报表(这里假设你已经有编译好的.jasper文件路径) String reportPath = "classpath:reports/your_report.jasper"; JasperFillManager.fillReport(reportPath, null, jrDataSource); // 后续的报表导出(PDF/Excel等)逻辑就按你自己的需求写啦 } }
这种方式的好处是不用自己写SQL查询,报表文件里的SQL会直接通过这个JdbcDataSource执行,非常适合报表逻辑已经定义在.jrxml里的场景。
方案2:先执行SQL拿到ResultSet,再转成JRResultSetDataSource
如果需要在代码里灵活控制查询逻辑(比如动态拼接SQL、传参数),那可以先借助Spring的JdbcTemplate执行查询,拿到ResultSet后再包装成JRResultSetDataSource。
代码示例
import org.springframework.jdbc.core.JdbcTemplate; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.data.JRResultSetDataSource; import java.sql.ResultSet; import java.sql.SQLException; import org.springframework.stereotype.Service; @Service public class JasperReportService { private final JdbcTemplate jdbcTemplate; public JasperReportService(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void generateDynamicReport() throws JRException, SQLException { // 1. 执行自定义SQL查询 String customSql = "SELECT id, name, email FROM users WHERE department = ?"; String department = "Engineering"; // 用JdbcTemplate执行查询,拿到ResultSet(用try-with-resources自动关闭资源) try (ResultSet rs = jdbcTemplate.getDataSource().getConnection() .prepareStatement(customSql) .setString(1, department) .executeQuery()) { // 2. 把ResultSet转换成JRDataSource JRResultSetDataSource jrDataSource = new JRResultSetDataSource(rs); // 3. 填充报表 String reportPath = "classpath:reports/dynamic_report.jasper"; JasperFillManager.fillReport(reportPath, null, jrDataSource); } } }
注意:这里用了try-with-resources语法自动关闭
ResultSet和Connection,避免资源泄漏。如果你用的是旧版Java,记得手动在finally块里关闭资源。
额外提醒
- 确保你的项目里已经引入了
jasperreports依赖(Maven/Gradle都可以),版本建议选稳定的最新版。 - 如果报表需要参数,可以在
JasperFillManager.fillReport的第二个参数里传入Map<String, Object>类型的参数映射。 - 如果你用的是Spring Boot,Spring会自动帮你配置好
DataSource和JdbcTemplate,直接注入就行,不用额外写配置类。
内容的提问来源于stack exchange,提问作者pheromix
相关产品推荐
相关产品推荐

