1 摘要

Jasper Report 作为老牌的报表导出工具,其客户端 Jaspersoft Studio 支持可视化创建导出模板,让不懂开发的业务人员也能够作出一张漂亮的报表,极大地降低了上手难度。本文将介绍在 Spring boot 中集成 Jasper Report 导出 PDF 的功能。

Jasper Report 官网: https://www.jaspersoft.com

关于 Jaspersoft Studio 的使用教程可参考:

玩转 Jasper Report(1) Jaspersoft Studio 安装使用教程

玩转 Jasper Report(2) Jaspersoft Studio 设置字体解决中文不显示问题

2 核心 Maven 依赖

./demo-common/pom.xml
        <!-- jasper report -->
        <dependency>
            <groupId>net.sf.jasperreports</groupId>
            <artifactId>jasperreports</artifactId>
            <version>${jasper-report.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.lowagie</groupId>
                    <artifactId>itext</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.lowagie</groupId>
            <artifactId>itext</artifactId>
            <version>${itext.version}</version>
        </dependency>
        <!-- jasper font extension -->
        <dependency>
            <groupId>net.sf.jasperreports</groupId>
            <artifactId>jasperreports-fonts</artifactId>
            <version>${jasper-report.version}</version>
        </dependency>
        <!-- 二维码 -->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>${google.zxing.version}</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>${google.zxing.version}</version>
        </dependency>

其中 ${jasper-report.version} 的版本为 6.16.0

${itext.version} 的版本为 2.1.7

${google.zxing.version} 的版本为 3.4.1

简要说明:

jasperreports 为 jasper report 的核心导出依赖

jasperreports-fonts 为 jasper report 的字体拓展依赖,引入该 jar 可以自定义添加第三方字体

iText 是用于渲染导出 PDF 的依赖,pasperreport 中的 iText 版本为 2.1.7.js8,该版本在 Maven 仓库中不存在,因此需要使用 Maven 仓库中有的版本

google.zxing 为谷歌的二维码生成依赖

3 核心代码

3.1 PDF 导出工具类
./demo-common/src/main/java/com/ljq/demo/springboot/common/util/JasperPdfUtil.java
package com.ljq.demo.springboot.common.util;

import cn.hutool.core.io.resource.ResourceUtil;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.util.JRLoader;

import java.io.FileNotFoundException;
import java.util.Map;

/**
 * @Description: jasper 导出工具类
 * @Author: junqiang.lu
 * @Date: 2021/2/4
 */
public class JasperPdfUtil {

    private JasperPdfUtil(){
    }

    /**
     * 导出 PDF
     *
     * @param templatePath jrxml 模板路径(base classpath)
     * @param paramMap 数据对象
     * @return
     * @throws FileNotFoundException
     * @throws JRException
     */
    public static byte[] exportPdfFromXml(String templatePath, Map<String, Object> paramMap) throws FileNotFoundException, JRException {
        JasperReport jasperReport = getJasperReportFromXml(templatePath);
        JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, paramMap, new JREmptyDataSource());
        return JasperExportManager.exportReportToPdf(jasperPrint);
    }

    /**
     * 导出 PDF
     *
     * @param templatePath jasper 模板路径(base classpath)
     * @param paramMap 数据对象
     * @return
     * @throws FileNotFoundException
     * @throws JRException
     */
    public static byte[] exportPdfFromJasper(String templatePath, Map<String, Object> paramMap) throws FileNotFoundException, JRException {
        JasperReport jasperReport = getJasperReportFromJasper(templatePath);
        JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, paramMap, new JREmptyDataSource());
        return JasperExportManager.exportReportToPdf(jasperPrint);
    }

    /**
     * 获取导出对象,从 xml 中
     *
     * @param templatePath 模板路径(base classpath)
     * @return
     * @throws FileNotFoundException
     * @throws JRException
     */
    private static JasperReport getJasperReportFromXml(String templatePath) throws FileNotFoundException, JRException {
        return JasperCompileManager.compileReport(ResourceUtil.getStream(templatePath));
    }


    /**
     * 获取导出对象,从 jasper 中
     * (jasper 为 jrxml 编译后生成的文件)
     *
     * @param templatePath 模板路径(base classpath)
     * @return
     * @throws FileNotFoundException
     * @throws JRException
     */
    private static JasperReport getJasperReportFromJasper(String templatePath) throws FileNotFoundException, JRException {
        return (JasperReport) JRLoader.loadObject(ResourceUtil.getStream(templatePath));
    }

}

注意事项:

Jaspert Report 的导出工具类不建议使用数据源,在 SpringBoot 项目中数据源统一由 Spring 管理。但是即使没有数据源也要传一个 new JREmptyDataSource() 来作为参数,否则如果使用 net.sf.jasperreports.engine.JasperFillManager#fillReport(net.sf.jasperreports.engine.JasperReport, java.util.Map<java.lang.String,java.lang.Object>) 方法,会抛异常

3.2 Jasper 导出模板 jrxml 文件
./demo-web/src/main/resources/contract.jrxml
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.16.0.final using JasperReports Library version 6.16.0-48579d909b7943b64690c65c71e07e0b80981928  -->
<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="contract_none" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="c1eeec34-e340-4152-82d1-741104a1b4bd">
	<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
	<parameter name="contractCode" class="java.lang.String">
		<parameterDescription><![CDATA[合同编号]]></parameterDescription>
	</parameter>
	<parameter name="contractName" class="java.lang.String">
		<parameterDescription><![CDATA[合同名称]]></parameterDescription>
	</parameter>
	<parameter name="contractOriginalCode" class="java.lang.String">
		<parameterDescription><![CDATA[合同原始编号]]></parameterDescription>
	</parameter>
	<parameter name="originalCcyTaxIncludedAmt" class="java.math.BigDecimal">
		<parameterDescription><![CDATA[合同原币金额]]></parameterDescription>
	</parameter>
	<parameter name="localCcyTaxIncludedAmt" class="java.math.BigDecimal">
		<parameterDescription><![CDATA[合同本币金额]]></parameterDescription>
	</parameter>
	<parameter name="contractType" class="java.lang.String">
		<parameterDescription><![CDATA[合同类型]]></parameterDescription>
	</parameter>
	<parameter name="contractDetailType" class="java.lang.String">
		<parameterDescription><![CDATA[合同明细类型]]></parameterDescription>
	</parameter>
	<parameter name="supplierName" class="java.lang.String">
		<parameterDescription><![CDATA[供应商名称]]></parameterDescription>
	</parameter>
	<parameter name="operatorName" class="java.lang.String">
		<parameterDescription><![CDATA[经办人名称]]></parameterDescription>
	</parameter>
	<parameter name="operatorOrgName" class="java.lang.String">
		<parameterDescription><![CDATA[经办机构名称]]></parameterDescription>
	</parameter>
	<parameter name="operatorDeptName" class="java.lang.String">
		<parameterDescription><![CDATA[经办部门名称]]></parameterDescription>
	</parameter>
	<parameter name="effectiveDate" class="java.util.Date">
		<parameterDescription><![CDATA[合同生效日期]]></parameterDescription>
	</parameter>
	<parameter name="expiredDate" class="java.util.Date">
		<parameterDescription><![CDATA[合同到期日]]></parameterDescription>
	</parameter>
	<queryString>
		<![CDATA[]]>
	</queryString>
	<background>
		<band splitType="Stretch"/>
	</background>
	<title>
		<band height="100" splitType="Stretch">
			<staticText>
				<reportElement x="150" y="0" width="100" height="100" uuid="bf0eca6a-bbe2-4428-9c12-bb5188fd1a28">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="华文宋体" size="16"/>
				</textElement>
				<text><![CDATA[合同名称:]]></text>
			</staticText>
			<textField>
				<reportElement x="250" y="0" width="300" height="100" uuid="a1cda531-2fbe-45b0-9712-3eabb6d9e27f">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="16"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{contractName}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="0" y="0" width="150" height="100" uuid="8473a83f-ab29-487b-970c-934e474335ef">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<text><![CDATA[]]></text>
			</staticText>
			<image>
				<reportElement x="5" y="5" width="145" height="95" uuid="f46728b5-d7ab-42a4-acf9-27918b0cdfcf">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<imageExpression><![CDATA[com.google.zxing.client.j2se.MatrixToImageWriter.toBufferedImage(
 new com.google.zxing.qrcode.QRCodeWriter().encode(
   $P{contractCode},
 com.google.zxing.BarcodeFormat.QR_CODE, 300, 300))]]></imageExpression>
			</image>
		</band>
	</title>
	<detail>
		<band height="464" splitType="Stretch">
			<textField>
				<reportElement x="80" y="0" width="195" height="50" uuid="105c1af1-a467-476b-bb55-d922f5430cf1">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font size="12"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{contractCode}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="0" y="0" width="275" height="50" uuid="2d6d679e-0c9f-4441-89b1-7967ab7921a1">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.rightIndent" value="pixel"/>
					<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
					<paragraph leftIndent="10"/>
				</textElement>
				<text><![CDATA[合同编号:]]></text>
			</staticText>
			<staticText>
				<reportElement x="275" y="0" width="275" height="50" uuid="d0d70e61-450b-4f07-b4ec-6fa32e324c5f">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.rightIndent" value="pixel"/>
					<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
					<paragraph leftIndent="10"/>
				</textElement>
				<text><![CDATA[原始合同编号:]]></text>
			</staticText>
			<textField>
				<reportElement x="375" y="0" width="175" height="50" uuid="6237f581-8f82-4a96-a8d8-e6bde73365ed">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{contractOriginalCode}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="0" y="50" width="275" height="50" uuid="c0dde391-626a-4a4d-a30e-9c6a96471094">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.rightIndent" value="pixel"/>
					<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
					<paragraph leftIndent="10"/>
				</textElement>
				<text><![CDATA[合同原币金额: ]]></text>
			</staticText>
			<textField pattern="#,###.000000">
				<reportElement x="100" y="50" width="175" height="50" uuid="31dffff6-2b8c-495d-a4ba-4f0dedcb5a2e">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{originalCcyTaxIncludedAmt}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="275" y="50" width="275" height="50" uuid="e58f269c-3bf0-4909-bf43-10c416490ef4">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.rightIndent" value="pixel"/>
					<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
					<paragraph leftIndent="10"/>
				</textElement>
				<text><![CDATA[合同本币金额: ]]></text>
			</staticText>
			<textField pattern="#,###.000000">
				<reportElement x="375" y="50" width="175" height="50" uuid="75671f56-f645-4d3b-9c23-a22aa9db24ac">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{localCcyTaxIncludedAmt}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="0" y="100" width="275" height="50" uuid="78effebc-f57c-4f42-8d9e-7e135bff5823">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.rightIndent" value="pixel"/>
					<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
					<paragraph leftIndent="10"/>
				</textElement>
				<text><![CDATA[合同类型: ]]></text>
			</staticText>
			<textField>
				<reportElement x="80" y="100" width="195" height="50" uuid="53bc851c-2240-4725-9f59-9b338b3ad673">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{contractType}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="275" y="100" width="275" height="50" uuid="b39bc59f-95ad-4710-a489-ee733633821a">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.rightIndent" value="pixel"/>
					<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
					<paragraph leftIndent="10"/>
				</textElement>
				<text><![CDATA[合同明细类型: ]]></text>
			</staticText>
			<textField>
				<reportElement x="380" y="100" width="175" height="50" uuid="c2934c57-e873-45b9-826e-4cb710371329">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{contractDetailType}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="0" y="150" width="275" height="50" uuid="9819c616-bdaa-4a3e-a6ba-9a4b32d83504">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.rightIndent" value="pixel"/>
					<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
					<paragraph leftIndent="10"/>
				</textElement>
				<text><![CDATA[供应商: ]]></text>
			</staticText>
			<textField>
				<reportElement x="75" y="150" width="200" height="50" uuid="a19b1811-472a-4a13-88c4-0a1de911be63">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{supplierName}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="275" y="150" width="275" height="50" uuid="ec87b19f-5c46-4cc0-a905-db71866a8bcb">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.rightIndent" value="pixel"/>
					<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
					<paragraph leftIndent="10"/>
				</textElement>
				<text><![CDATA[经办人: ]]></text>
			</staticText>
			<textField>
				<reportElement x="360" y="150" width="190" height="50" uuid="51924948-0620-4640-83f1-2dccde027ce7">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{operatorName}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="0" y="200" width="275" height="50" uuid="be7ce37b-e71c-4672-81ca-1107c7c63aa3">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.rightIndent" value="pixel"/>
					<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
					<paragraph leftIndent="10"/>
				</textElement>
				<text><![CDATA[经办机构: ]]></text>
			</staticText>
			<textField>
				<reportElement x="80" y="200" width="195" height="50" uuid="0ec536ab-e009-4f1b-a53d-b5e6cf4a7517">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{operatorOrgName}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="275" y="200" width="275" height="50" uuid="ddfd21bf-8765-47ac-9b9f-1df0723d4a6e">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.rightIndent" value="pixel"/>
					<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
					<paragraph leftIndent="10"/>
				</textElement>
				<text><![CDATA[经办部门: ]]></text>
			</staticText>
			<textField>
				<reportElement x="380" y="200" width="170" height="50" uuid="c9fd0aeb-4107-4e50-98b6-ceeb92dd1f9e">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{operatorDeptName}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="0" y="250" width="275" height="50" uuid="7a44b93c-dbf8-4b89-84b1-17526e7a42fd">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.rightIndent" value="pixel"/>
					<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
					<paragraph leftIndent="10"/>
				</textElement>
				<text><![CDATA[合同生效日: ]]></text>
			</staticText>
			<textField pattern="yyyy-MM-dd">
				<reportElement x="100" y="250" width="175" height="50" uuid="6e66816d-8d93-4384-8e67-b4e706cd32af">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{effectiveDate}]]></textFieldExpression>
			</textField>
			<staticText>
				<reportElement x="275" y="250" width="275" height="50" uuid="bbeb9256-f69e-4e23-9ea2-7e50336f3953">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
					<property name="com.jaspersoft.studio.unit.rightIndent" value="pixel"/>
					<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
				</reportElement>
				<box>
					<topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
					<rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
				</box>
				<textElement verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
					<paragraph leftIndent="10"/>
				</textElement>
				<text><![CDATA[合同到期日: ]]></text>
			</staticText>
			<textField pattern="yyyy-MM-dd">
				<reportElement x="380" y="250" width="170" height="50" uuid="b7733675-2d10-4bfb-ac51-7b4674b7bde0">
					<property name="com.jaspersoft.studio.unit.x" value="px"/>
					<property name="com.jaspersoft.studio.unit.y" value="px"/>
					<property name="com.jaspersoft.studio.unit.width" value="px"/>
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<textElement textAlignment="Left" verticalAlignment="Middle">
					<font fontName="华文宋体" size="12"/>
				</textElement>
				<textFieldExpression><![CDATA[$P{expiredDate}]]></textFieldExpression>
			</textField>
		</band>
	</detail>
	<pageFooter>
		<band height="54" splitType="Stretch"/>
	</pageFooter>
	<summary>
		<band height="42" splitType="Stretch"/>
	</summary>
</jasperReport>

3.3 自定义字体配置

字体文件

./demo-web/src/main/resources/static/font/stsong.ttf

字体配置文件

./demo-web/src/main/resources/static/font/fonts.xml
<?xml version="1.0" encoding="UTF-8"?>
<fontFamilies>
    <fontFamily name="华文宋体">
        <normal>static/font/stsong.ttf</normal>
        <bold>static/font/stsong.ttf</bold>
        <italic>static/font/stsong.ttf</italic>
        <boldItalic>static/font/stsong.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>

Jasper 拓展拓展配置,在项目运行时会加载该信息

./demo-web/src/main/resources/jasperreports_extension.properties
net.sf.jasperreports.extension.registry.factory.simple.font.families=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
net.sf.jasperreports.extension.simple.font.families.lobstertwo=static/font/fonts.xml

Japer jrxml 模板中的字体必须与fonts.xml 中配置的字体名称保持一致才会生效

3.4 二维码设置

在 Jaspersoft Studio 中拖拽一个「Image」标签至布局界面,设置图片的「Expression」表达式属性

image-20210210111032740

表达式为:

com.google.zxing.client.j2se.MatrixToImageWriter.toBufferedImage(
 new com.google.zxing.qrcode.QRCodeWriter().encode(
   $P{contractCode},
 com.google.zxing.BarcodeFormat.QR_CODE, 300, 300))

其中 $P{contractCode} 即为所需要生成二维码的参数

3.5 PDF导出Service示例
./demo-service/src/main/java/com/ljq/demo/springboot/service/CommonService.java
package com.ljq.demo.springboot.service;

import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import com.ljq.demo.springboot.baseweb.api.ApiResult;
import com.ljq.demo.springboot.baseweb.exception.ParamsCheckException;
import com.ljq.demo.springboot.vo.DownloadBean;
import net.sf.jasperreports.engine.JRException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * @Description: 公共业务
 * @Author: junqiang.lu
 * @Date: 2018/12/24
 */
public interface CommonService {

    /**
     * PDF 文件导出 2
     *
     * @return
     */
    byte[] exportPdf2() throws FileNotFoundException, JRException;


}

Service 实现类

./demo-service/src/main/java/com/ljq/demo/springboot/service/impl/CommonServiceImpl.java
package com.ljq.demo.springboot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.StrUtil;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import com.ljq.demo.springboot.baseweb.api.ApiResult;
import com.ljq.demo.springboot.baseweb.api.ResponseCode;
import com.ljq.demo.springboot.baseweb.config.OSSConfig;
import com.ljq.demo.springboot.baseweb.config.PDFExportConfig;
import com.ljq.demo.springboot.baseweb.config.SftpUploadConfig;
import com.ljq.demo.springboot.baseweb.exception.ParamsCheckException;
import com.ljq.demo.springboot.baseweb.util.OSSBootUtil;
import com.ljq.demo.springboot.baseweb.util.OSSSingleUtil;
import com.ljq.demo.springboot.baseweb.util.PDFUtil;
import com.ljq.demo.springboot.baseweb.util.ResourceFileUtil;
import com.ljq.demo.springboot.common.util.JasperPdfUtil;
import com.ljq.demo.springboot.common.util.SftpUtil;
import com.ljq.demo.springboot.entity.ContractEntity;
import com.ljq.demo.springboot.service.CommonService;
import com.ljq.demo.springboot.vo.DownloadBean;
import lombok.extern.slf4j.Slf4j;
import net.sf.jasperreports.engine.JRException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @Description: 公共业务具体实现类
 * @Author: junqiang.lu
 * @Date: 2018/12/24
 */
@Slf4j
@Service("commonService")
public class CommonServiceImpl implements CommonService {

    /**
     * PDF 文件导出 2
     *
     * @return
     */
    @Override
    public byte[] exportPdf2() throws FileNotFoundException, JRException {
        String templatePath = "contract.jrxml";
        ContractEntity contract = new ContractEntity();
        contract.setContractCode("CON11123445567778888");
        contract.setContractName("马尔代夫海景房转让合同");
        contract.setContractOriginalCode("ORI555444333222111");
        contract.setOriginalCcyTaxIncludedAmt(new BigDecimal(123456789.12345666666)
                .setScale(6,BigDecimal.ROUND_DOWN));
        contract.setLocalCcyTaxIncludedAmt(new BigDecimal(987654321.123456));
        contract.setContractType("租赁合同");
        contract.setContractDetailType("房屋租赁合同");
        contract.setSupplierName("太平洋租房股份有限公司");
        contract.setOperatorName("德玛西亚");
        contract.setOperatorOrgName("稀里糊涂银行总行");
        contract.setOperatorDeptName("马尔代夫总行财务部");
        contract.setEffectiveDate(new Date());
        contract.setExpiredDate(new Date());
        return JasperPdfUtil.exportPdfFromXml(templatePath, BeanUtil.beanToMap(contract));
    }

}

3.6 Controller 层代码
./demo-web/src/main/java/com/ljq/demo/springboot/web/controller/CommonController.java
package com.ljq.demo.springboot.web.controller;

import cn.hutool.core.date.DateUtil;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import com.ljq.demo.springboot.baseweb.api.ApiResult;
import com.ljq.demo.springboot.baseweb.exception.ParamsCheckException;
import com.ljq.demo.springboot.common.annotation.ParamsCheck;
import com.ljq.demo.springboot.service.CommonService;
import com.ljq.demo.springboot.vo.DownloadBean;
import io.swagger.annotations.ApiOperation;
import net.sf.jasperreports.engine.JRException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;

/**
 * @Description: 公共模块控制中心
 * @Author: junqiang.lu
 * @Date: 2018/12/24
 */
@RestController
@RequestMapping("api/demo/common")
public class CommonController {

    private static final Logger logger = LoggerFactory.getLogger(CommonController.class);

    @Autowired
    private CommonService commonService;

    /**
     * PDF 导出 2
     * 基于 Jasper iReport
     *
     * @return
     * @throws FileNotFoundException
     * @throws JRException
     */
    @GetMapping(value = "/export/pdf/2", produces = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation(value = "PDF 导出2(基于Jasper iReport)", notes = "PDF 导出2(基于Jasper iReport)")
    public ResponseEntity<byte[]> exportPdf2() throws FileNotFoundException, JRException {
        String fileName = "contract" + DateUtil.format(new Date(), "yyyy-MM-dd") + ".pdf";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentDispositionFormData("attachment", fileName);
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<>(commonService.exportPdf2(), headers, HttpStatus.OK);
    }

}

3.7 导出对象实体类
./demo-model/src/main/java/com/ljq/demo/springboot/entity/ContractEntity.java
package com.ljq.demo.springboot.entity;

import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;

/**
 * @Description: 合同实体类
 * @Author: junqiang.lu
 * @Date: 2021/2/4
 */
@Data
public class ContractEntity implements Serializable {

    private static final long serialVersionUID = -9180267794196864281L;

    /**
     * 合同编码
     * */
    private String contractCode;
    /**
     * 合同原始编码
     * */
    private String contractOriginalCode;
    /**
     * 合同名称
     * */
    private String contractName;
    /**
     * 合同类型
     * */
    private String contractType;
    /**
     * 合同明细类型
     * */
    private String contractDetailType;
    /**
     * 合同生效日期
     * */
    private Date effectiveDate;
    /**
     * 合同到期日
     * */
    private Date expiredDate;
    /**
     * 合同原币含税金额
     * */
    private BigDecimal originalCcyTaxIncludedAmt;
    /**
     * 合同本币含税金额
     * */
    private BigDecimal localCcyTaxIncludedAmt;
    /**
     * 供应商名称
     * */
    private String supplierName;
    /**
     * 经办人名字
     * */
    private String operatorName;
    /**
     * 经办人部门名字
     * */
    private String operatorDeptName;
    /**
     * 经办人机构名字
     * */
    private String operatorOrgName;

}

4 导出测试

4.1 请求参数

image-20210210112819842

4.2 PDF导出示例

image-20210210113254881

至此,Spring Boot 集成 Jasper Report 导出PDF的功能已经完成

5 推荐参考资料

Jaspersoft Studio 可视化编辑器下载

TIBCO Jaspersoft Studio 报表软件使用教程

Java | Simple Jasper Report Example

JasperReports with Spring

Custom Font with the Font Extension

Add Custom Fonts to Jasper Report in Java

Jaspersoft 与springboot结合生成一维码,二维码

Change Date and Time Format in TIBCO JasperReports® Server Web UI and Report Output

How do I format a number as 2.564.894.621 in JasperSoft Studio?

6 Github 源码

Gtihub 源码地址 : https://github.com/Flying9001/springBootDemo

个人公众号:404Code,分享半个互联网人的技术与思考,感兴趣的可以关注.
404Code

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐