1. 程式人生 > 其它 >Spring Boot整合JasperReports生成PDF文件

Spring Boot整合JasperReports生成PDF文件

由於工作需要,要實現後端根據模板動態填充資料生成PDF文件,通過技術選型,使用Ireport5.6來設計模板,結合JasperReports5.6工具庫來呼叫渲染生成PDF文件。本人文采欠缺,寫作能力差,下面粗略的介紹其使用步驟,若有不對的地方,望大家莫噴,謝謝!

一、使用Ireport designer 5.6設計模板

ireport的使用由於時間關係不便多說,設計好之後,將其進行編譯生成jasper檔案,然後將其拷貝放置於專案某個目錄下,以供訪問獲取該檔案。

二、在Spring Boot專案中引入依賴包

<!-- jasperreports-->
<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>6.0.0</version>
</dependency>
<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports-fonts</artifactId>
    <version>6.0.0</version>
</dependency>
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.0</version>
</dependency>
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-pdfa</artifactId>
    <version>5.5.0</version>
</dependency>
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
</dependency>
<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-all</artifactId>
    <version>2.4.11</version>
</dependency>

三、自定義spring mvc通用匯出PDF檢視類PdfReportView(繼承自AbstractView )

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import org.springframework.web.servlet.view.AbstractView;

public class PdfReportView extends AbstractView {

    private static final String CONTENT_TYPE = "application/pdf";

    private String templatePath;
    private String exportFileName;

    public PdfReportView(String templatePath, String exportFileName) {
        this.templatePath = templatePath;
        if (exportFileName != null) {
            try {
                exportFileName = URLEncoder.encode(exportFileName, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        this.exportFileName = exportFileName;
        setContentType(CONTENT_TYPE);
    }

    protected Map<String, Object> getParamsMap(Map<String, Object> map) throws Exception {
        Map<String, Object> params = new HashMap<>();
        for (String key : map.keySet()) {
            Object val = map.get(key);
            if (val instanceof JRDataSource) {
                continue;
            } else {
                params.put(key, val);
            }
        }
        return params;
    }

    protected JRDataSource getDataSource(Map<String, Object> map) throws Exception {
        for (String key : map.keySet()) {
            Object val = map.get(key);
            if (val instanceof JRDataSource) {
                return (JRDataSource) map.get(key);
            }
        }
        return new JREmptyDataSource();
    }

    @Override
    protected void renderMergedOutputModel(Map<String, Object> map,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception {

        response.setCharacterEncoding("utf-8");
        response.setContentType(getContentType());
        //response.setContentType("application/octet-stream");
        response.setHeader("content-disposition", "attachment;filename=" + exportFileName + ".pdf");

        try (InputStream inputStream = Thread.currentThread().getContextClassLoader()
            .getResourceAsStream(templatePath)) {
            try (OutputStream ouputStream = response.getOutputStream()) {

                JasperPrint jasperPrint = JasperFillManager
                    .fillReport(inputStream, getParamsMap(map), getDataSource(map));

                JasperExportManager.exportReportToPdfStream(jasperPrint, ouputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

四、spring mvc呼叫案例

Map<String, Object> map = new HashMap<>();
List<Map<String,Object>> dataList = ....
map.put("users", new JRMapCollectionDataSource(dataList));
map.put("title", "報表名稱");
return new ModelAndView(new PdfReportView("templates/report/resume.jasper", "professors"),map);

五、解決linux下宋體渲染問題

1、在src/main/resources路徑下新建jasperreports_extension.properties檔案,內容如下:

net.sf.jasperreports.awt.ignore.missing.font=true
net.sf.jasperreports.extension.registry.factory.simple.font.families=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
net.sf.jasperreports.extension.simple.font.families.dejavu=fonts/fonts.xml

2、在src/main/resources路徑下新建fonts目錄,並新建fonts.xml檔案,內容如下:

<?xml version="1.0" encoding="UTF-8"?>

<fontFamilies>

    <fontFamily name="DejaVu Sans">
        <normal>net/sf/jasperreports/fonts/dejavu/DejaVuSans.ttf</normal>
        <bold>net/sf/jasperreports/fonts/dejavu/DejaVuSans-Bold.ttf</bold>
        <italic>net/sf/jasperreports/fonts/dejavu/DejaVuSans-Oblique.ttf</italic>
        <boldItalic>net/sf/jasperreports/fonts/dejavu/DejaVuSans-BoldOblique.ttf</boldItalic>
        <pdfEncoding>Identity-H</pdfEncoding>
        <pdfEmbedded>true</pdfEmbedded>
        <exportFonts>
            <export key="net.sf.jasperreports.html">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
            <export key="net.sf.jasperreports.xhtml">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
        </exportFonts>
        <!--
    <locales>
      <locale>en_US</locale>
      <locale>de_DE</locale>
    </locales>
    -->
    </fontFamily>

    <fontFamily name="DejaVu Serif">
        <normal>net/sf/jasperreports/fonts/dejavu/DejaVuSerif.ttf</normal>
        <bold>net/sf/jasperreports/fonts/dejavu/DejaVuSerif-Bold.ttf</bold>
        <italic>net/sf/jasperreports/fonts/dejavu/DejaVuSerif-Italic.ttf</italic>
        <boldItalic>net/sf/jasperreports/fonts/dejavu/DejaVuSerif-BoldItalic.ttf</boldItalic>
        <pdfEncoding>Identity-H</pdfEncoding>
        <pdfEmbedded>true</pdfEmbedded>
        <exportFonts>
            <export key="net.sf.jasperreports.html">'DejaVu Serif', 'Times New Roman', Times, serif</export>
            <export key="net.sf.jasperreports.xhtml">'DejaVu Serif', 'Times New Roman', Times, serif</export>
        </exportFonts>
    </fontFamily>

    <fontFamily name="DejaVu Sans Mono">
        <normal>net/sf/jasperreports/fonts/dejavu/DejaVuSansMono.ttf</normal>
        <bold>net/sf/jasperreports/fonts/dejavu/DejaVuSansMono-Bold.ttf</bold>
        <italic>net/sf/jasperreports/fonts/dejavu/DejaVuSansMono-Oblique.ttf</italic>
        <boldItalic>net/sf/jasperreports/fonts/dejavu/DejaVuSansMono-BoldOblique.ttf</boldItalic>
        <pdfEncoding>Identity-H</pdfEncoding>
        <pdfEmbedded>true</pdfEmbedded>
        <exportFonts>
            <export key="net.sf.jasperreports.html">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export>
            <export key="net.sf.jasperreports.xhtml">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export>
        </exportFonts>
    </fontFamily>
    <fontFamily name="SansSerif">
        <exportFonts>
            <export key="net.sf.jasperreports.html">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
            <export key="net.sf.jasperreports.xhtml">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
        </exportFonts>
    </fontFamily>
    <fontFamily name="Serif">
        <exportFonts>
            <export key="net.sf.jasperreports.html">'DejaVu Serif', 'Times New Roman', Times, serif</export>
            <export key="net.sf.jasperreports.xhtml">'DejaVu Serif', 'Times New Roman', Times, serif</export>
        </exportFonts>
    </fontFamily>
    <fontFamily name="Monospaced">
        <exportFonts>
            <export key="net.sf.jasperreports.html">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export>
            <export key="net.sf.jasperreports.xhtml">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export>
        </exportFonts>
    </fontFamily>

    <fontFamily name="宋體">
        <normal>fonts/simsun.ttf</normal>
        <bold>fonts/simsun.ttf</bold>
        <italic>fonts/simsun.ttf</italic>
        <boldItalic>fonts/simsun.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>

3、在src/main/resources/fonts目錄放入宋體字型檔案 simsun.ttf