You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring4升级Spring5时JasperReports项目迁移问题求助

解决Spring 5.x移除JasperReports视图支持的替代方案

嘿,你遇到的这个问题很典型——Spring 5.x确实移除了org.springframework.web.servlet.view.jasperreports包下的所有视图类,官方给出的原因是要减少框架的冗余依赖,把这类第三方集成的工作交给开发者自己处理。不过别担心,有两个非常实用的替代方案:

方案一:直接使用JasperReports原生API生成PDF

这个方案最直接,跳过Spring的视图封装,在Controller里直接调用Jasper的API完成PDF生成和输出,灵活性更高。

示例代码如下:

import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

@RestController
public class ReportController {

    private final ResourceLoader resourceLoader;

    public ReportController(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @GetMapping("/purchase-pdf")
    public void generatePurchasePdf(HttpServletResponse response) throws Exception {
        // 1. 加载jrxml文件
        Resource resource = resourceLoader.getResource("classpath:reports/purchaseReport.jrxml");
        InputStream inputStream = resource.getInputStream();
        
        // 2. 编译报表模板
        JasperReport jasperReport = JasperCompileManager.compileReport(inputStream);
        
        // 3. 准备报表参数和数据源(对应原来的reportDataKey="datasource")
        Map<String, Object> parameters = new HashMap<>();
        JRDataSource dataSource = // 这里传入你的数据源,比如JREmptyDataSource、JRBeanCollectionDataSource等
        
        // 4. 填充报表数据
        JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
        
        // 5. 输出PDF到响应
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "attachment; filename=\"purchaseReport.pdf\"");
        
        JRPdfExporter exporter = new JRPdfExporter();
        exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
        exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(response.getOutputStream()));
        exporter.exportReport();
    }
}

方案二:自定义Spring View实现(兼容原有视图解析逻辑)

如果想保留原来的XML视图配置风格,你可以自己实现一个View类,模仿原来JasperReportsPdfView的功能,这样不需要大幅修改现有代码结构。

步骤1:自定义Jasper PDF View类

import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.servlet.view.AbstractView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

public class CustomJasperReportsPdfView extends AbstractView {

    private String url; // 对应原来的p:url属性
    private String reportDataKey = "datasource"; // 对应原来的p:reportDataKey属性
    private final ResourceLoader resourceLoader;

    public CustomJasperReportsPdfView(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
        setContentType("application/pdf");
    }

    @Override
    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 加载并编译报表模板
        Resource resource = resourceLoader.getResource(url);
        JasperReport jasperReport = JasperCompileManager.compileReport(resource.getInputStream());
        
        // 获取数据源
        JRDataSource dataSource = (JRDataSource) model.get(reportDataKey);
        
        // 填充报表
        JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, model, dataSource);
        
        // 输出PDF
        response.setHeader("Content-Disposition", "attachment; filename=\"report.pdf\"");
        JRPdfExporter exporter = new JRPdfExporter();
        exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
        exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(response.getOutputStream()));
        exporter.exportReport();
    }

    // 提供setter方法供XML配置使用
    public void setUrl(String url) {
        this.url = url;
    }

    public void setReportDataKey(String reportDataKey) {
        this.reportDataKey = reportDataKey;
    }
}

步骤2:修改XML视图配置

把原来的JasperReportsPdfView替换成你自定义的类:

<!-- jasper-view.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-5.2.xsd">

<bean id="purchasePdf" class="com.yourpackage.CustomJasperReportsPdfView" 
      p:url="classpath:reports/purchaseReport.jrxml" 
      p:reportDataKey="datasource" />
</beans>

注意要把com.yourpackage替换成你实际的包路径,同时确保ResourceLoader能被Spring自动注入(Spring 5.x会自动识别构造函数中的依赖)。

额外注意事项

  • 确保你的jasperreports依赖版本(6.4.0)兼容Java 11和Spring 5.2.5.RELEASE,这个版本是没问题的。
  • 如果报表模板不需要动态编译,可以提前编译成.jasper文件,然后直接加载编译后的文件,提升性能:JasperCompileManager.compileReportToFile(inputStream, "purchaseReport.jasper"),后续用JasperFillManager.fillReport("purchaseReport.jasper", parameters, dataSource)加载。

内容的提问来源于stack exchange,提问作者B378

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 09:32:46