Spring Boot | Spring Boot整合JasperReports下载PDF报表文件

1,665 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

主要功能点:

Spring Boot Web 整合 JasperReports,在浏览器地址栏输入访问地址会直接下载 PDF 报表文件;整合过程中遇到的两个比较费时间的问题:

  1. Maven 依赖包下载失败:Cannot resolve com.lowagie:itext:2.1.7.js8 ;
  2. 生成的 PDF 文件中中文不显示。

1、Maven 依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>net.sf.jasperreports</groupId>
	<artifactId>jasperreports</artifactId>
	<version>6.19.1</version>
	<exclusions>
		<exclusion>
			<groupId>com.lowagie</groupId>
			<artifactId>itext</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>net.sf.jasperreports</groupId>
	<artifactId>jasperreports-fonts</artifactId>
	<version>6.19.1</version>
</dependency>
<dependency>
	<groupId>com.lowagie</groupId>
	<artifactId>itext</artifactId>
	<version>2.1.7</version>
</dependency>

2、报表内容

报表文件名称:employees-details.jrxml

报表文件路径:src\main\resources\employees-details.jrxml

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.19.1.final using JasperReports Library version 6.19.1-867c00bf88cd4d784d404379d6c05e1b419e8a4c  -->
<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="Employee" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="37175dba-8b89-474d-8341-09d431dce38f">
	<style name="Table_TH" mode="Opaque" backcolor="#F0F8FF">
		<box>
			<pen lineWidth="0.5" lineColor="#000000"/>
			<topPen lineWidth="0.5" lineColor="#000000"/>
			<leftPen lineWidth="0.5" lineColor="#000000"/>
			<bottomPen lineWidth="0.5" lineColor="#000000"/>
			<rightPen lineWidth="0.5" lineColor="#000000"/>
		</box>
	</style>
	<style name="Table_TD" mode="Opaque" backcolor="#FFFFFF">
		<box>
			<pen lineWidth="0.5" lineColor="#000000"/>
			<topPen lineWidth="0.5" lineColor="#000000"/>
			<leftPen lineWidth="0.5" lineColor="#000000"/>
			<bottomPen lineWidth="0.5" lineColor="#000000"/>
			<rightPen lineWidth="0.5" lineColor="#000000"/>
		</box>
	</style>
	<style name="Table_CH" mode="Opaque" backcolor="#BFE1FF">
		<box>
			<pen lineWidth="0.5" lineColor="#000000"/>
			<topPen lineWidth="0.5" lineColor="#000000"/>
			<leftPen lineWidth="0.5" lineColor="#000000"/>
			<bottomPen lineWidth="0.5" lineColor="#000000"/>
			<rightPen lineWidth="0.5" lineColor="#000000"/>
		</box>
	</style>
	<subDataset name="Dataset1" uuid="01ae53ec-87c9-41de-867d-bd79f5d4e77c">
		<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
		<queryString>
			<![CDATA[]]>
		</queryString>
		<field name="id" class="java.lang.Integer"/>
		<field name="name" class="java.lang.String"/>
		<field name="role" class="java.lang.String"/>
		<field name="address" class="java.lang.String"/>
		<sortField name="id"/>
		<variable name="totalEmployees" class="java.lang.Integer" calculation="DistinctCount">
			<variableExpression><![CDATA[$F{id}]]></variableExpression>
		</variable>
	</subDataset>
	<parameter name="CompanyName" class="java.lang.String"/>
	<parameter name="employeeData" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
	<queryString>
		<![CDATA[]]>
	</queryString>
	<field name="name" class="java.lang.String"/>
	<field name="id" class="java.lang.Integer"/>
	<field name="role" class="java.lang.String"/>
	<field name="address" class="java.lang.String"/>
	<background>
		<band splitType="Stretch"/>
	</background>
	<title>
		<band height="86" splitType="Stretch">
			<frame>
				<reportElement mode="Opaque" x="0" y="0" width="555" height="86" backcolor="#3BE3E3" uuid="57f80b95-2c82-4855-8b4f-797057ea6a99"/>
				<image scaleImage="FillFrame">
					<reportElement x="82" y="0" width="410" height="40" uuid="c21b5d52-4d05-448d-a001-a0cd19a9aeb2"/>
					<imageExpression><![CDATA["E:/1.png"]]></imageExpression>
				</image>
				<textField>
					<reportElement style="Table_TH" mode="Transparent" x="90" y="50" width="400" height="30" backcolor="#FFFFFF" uuid="15957312-bfcc-43e7-ad7c-8cdb97c4197b">
						<property name="com.jaspersoft.studio.unit.width" value="px"/>
					</reportElement>
					<box padding="0">
						<pen lineWidth="1.0" lineStyle="Solid"/>
						<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
						<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
						<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
						<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
					</box>
					<textElement>
						<font fontName="华文宋体" size="20" isBold="true" isItalic="true" isUnderline="true"/>
					</textElement>
					<textFieldExpression><![CDATA[$P{CompanyName}]]></textFieldExpression>
				</textField>
			</frame>
		</band>
	</title>
	<pageHeader>
		<band height="31" splitType="Stretch">
			<line>
				<reportElement x="0" y="15" width="555" height="1" uuid="04a9c4d5-af68-4738-b280-249876a779f3">
					<property name="com.jaspersoft.studio.unit.height" value="px"/>
				</reportElement>
				<graphicElement>
					<pen lineStyle="Dashed"/>
				</graphicElement>
			</line>
		</band>
	</pageHeader>
	<detail>
		<band height="170" splitType="Stretch">
			<property name="com.jaspersoft.studio.unit.height" value="px"/>
			<componentElement>
				<reportElement x="0" y="0" width="555" height="170" uuid="58650125-3653-4fa6-9154-b9c084419a71">
					<property name="com.jaspersoft.studio.layout" value="com.jaspersoft.studio.editor.layout.VerticalRowLayout"/>
					<property name="com.jaspersoft.studio.table.style.table_header" value="Table_TH"/>
					<property name="com.jaspersoft.studio.table.style.column_header" value="Table_CH"/>
					<property name="com.jaspersoft.studio.table.style.detail" value="Table_TD"/>
				</reportElement>
				<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
					<datasetRun subDataset="Dataset1" uuid="33e34648-091e-48f9-b2c9-2defadbd03fb">
						<dataSourceExpression><![CDATA[$P{employeeData}]]></dataSourceExpression>
					</datasetRun>
					<jr:column width="100" uuid="fed73b20-211a-48ef-bf45-eb5f50e0d41b">
						<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column1"/>
						<jr:tableFooter style="Table_TH" height="30" rowSpan="1">
							<staticText>
								<reportElement x="0" y="0" width="100" height="30" uuid="b219724f-df88-4066-8fc3-db986efed088"/>
								<textElement textAlignment="Center" verticalAlignment="Middle"/>
								<text><![CDATA[Total Employees = ]]></text>
							</staticText>
						</jr:tableFooter>
						<jr:columnHeader style="Table_CH" height="30" rowSpan="1">
							<staticText>
								<reportElement x="0" y="0" width="100" height="30" uuid="6e4a6eb9-7503-46c2-b199-cb78736d4827"/>
								<textElement textAlignment="Center" verticalAlignment="Middle">
									<font fontName="华文宋体"/>
								</textElement>
								<text><![CDATA[ID]]></text>
							</staticText>
						</jr:columnHeader>
						<jr:columnFooter style="Table_CH" height="30" rowSpan="1"/>
						<jr:detailCell style="Table_TD" height="30">
							<textField>
								<reportElement x="0" y="0" width="100" height="30" uuid="e04148fe-4406-4817-bf7c-a75a1837a834"/>
								<textElement textAlignment="Center" verticalAlignment="Middle">
									<font fontName="华文宋体"/>
								</textElement>
								<textFieldExpression><![CDATA[$F{id}]]></textFieldExpression>
							</textField>
						</jr:detailCell>
					</jr:column>
					<jr:column width="100" uuid="c805b32b-9978-4ad9-93c8-64fb6ebdc310">
						<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column2"/>
						<jr:tableFooter style="Table_TH" height="30" rowSpan="1">
							<textField>
								<reportElement x="0" y="0" width="100" height="30" uuid="8b6f3603-5468-4ed8-92d6-2744856cfbec"/>
								<textElement textAlignment="Center" verticalAlignment="Middle"/>
								<textFieldExpression><![CDATA[$V{totalEmployees}]]></textFieldExpression>
							</textField>
						</jr:tableFooter>
						<jr:columnHeader style="Table_CH" height="30" rowSpan="1">
							<staticText>
								<reportElement x="0" y="0" width="100" height="30" uuid="ae32a33c-1f5c-4045-b8d6-738226f2881e"/>
								<textElement textAlignment="Center" verticalAlignment="Middle">
									<font fontName="华文宋体"/>
								</textElement>
								<text><![CDATA[员工姓名]]></text>
							</staticText>
						</jr:columnHeader>
						<jr:columnFooter style="Table_CH" height="30" rowSpan="1"/>
						<jr:detailCell style="Table_TD" height="30">
							<textField>
								<reportElement x="0" y="0" width="100" height="30" uuid="ce7df570-525d-4bb1-9ed3-a63c0b387bbd"/>
								<textElement textAlignment="Center" verticalAlignment="Middle">
									<font fontName="华文宋体"/>
								</textElement>
								<textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
							</textField>
						</jr:detailCell>
					</jr:column>
					<jr:column width="40" uuid="bd04119c-8493-4333-952a-2aeac29db62b">
						<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column3"/>
						<jr:tableFooter style="Table_TH" height="30" rowSpan="1"/>
						<jr:columnHeader style="Table_CH" height="30" rowSpan="1">
							<staticText>
								<reportElement x="0" y="0" width="40" height="30" uuid="37ee0454-22df-4056-a40e-f52f82d29f95"/>
								<textElement textAlignment="Center" verticalAlignment="Middle">
									<font fontName="华文宋体"/>
								</textElement>
								<text><![CDATA[角色]]></text>
							</staticText>
						</jr:columnHeader>
						<jr:columnFooter style="Table_CH" height="30" rowSpan="1"/>
						<jr:detailCell style="Table_TD" height="30">
							<textField>
								<reportElement x="0" y="0" width="40" height="30" uuid="a789a863-4232-4279-8a66-be83206747fe"/>
								<textElement textAlignment="Center" verticalAlignment="Middle">
									<font fontName="华文宋体"/>
								</textElement>
								<textFieldExpression><![CDATA[$F{role}]]></textFieldExpression>
							</textField>
						</jr:detailCell>
					</jr:column>
					<jr:column width="200" uuid="f32f724a-24c9-4887-ba41-5957dd0fed1d">
						<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column4"/>
						<jr:tableFooter style="Table_TH" height="30" rowSpan="1"/>
						<jr:columnHeader style="Table_CH" height="30" rowSpan="1">
							<staticText>
								<reportElement x="0" y="0" width="200" height="30" uuid="ced8b636-0cef-488f-89c4-9988b81415db"/>
								<textElement textAlignment="Center" verticalAlignment="Middle">
									<font fontName="华文宋体"/>
								</textElement>
								<text><![CDATA[地址]]></text>
							</staticText>
						</jr:columnHeader>
						<jr:columnFooter style="Table_CH" height="30" rowSpan="1">
							<property name="com.jaspersoft.studio.unit.width" value="px"/>
						</jr:columnFooter>
						<jr:detailCell style="Table_TD" height="30">
							<textField>
								<reportElement x="0" y="0" width="200" height="30" uuid="958c39bd-fd6f-4414-9700-579e0c8ee7d9"/>
								<textElement textAlignment="Center" verticalAlignment="Middle">
									<font fontName="华文宋体"/>
								</textElement>
								<textFieldExpression><![CDATA[$F{address}]]></textFieldExpression>
							</textField>
						</jr:detailCell>
					</jr:column>
				</jr:table>
			</componentElement>
		</band>
	</detail>
	<pageFooter>
		<band height="50" splitType="Stretch">
			<textField>
				<reportElement x="350" y="20" width="100" height="30" uuid="9ab9485d-d510-496f-9dcd-dae944a4ae43"/>
				<textElement textAlignment="Right"/>
				<textFieldExpression><![CDATA["Page " + $V{PAGE_NUMBER}]]></textFieldExpression>
			</textField>
			<textField evaluationTime="Report">
				<reportElement x="455" y="20" width="100" height="30" uuid="a534e5d1-aa1b-4a87-9149-d7a052cbc01f"/>
				<textFieldExpression><![CDATA[" of " + $V{PAGE_NUMBER}]]></textFieldExpression>
			</textField>
		</band>
	</pageFooter>
</jasperReport>

3、字体配置

字体文件位置:src\main\resources\static\font\chinese.stsong.ttf

字体配置文件位置:src\main\resources\static\font\fonts.xml

配置文件内容

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

在 classpath 路径下(application.properties 同级)创建 Jasper 拓展文件 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

4、实体对象 —— Employee.java

@Data
@NoArgsConstructor
public class Employee {

	private int id;
	private String name;
	private String role;
	private String address;

	public Employee(int id, String name, String role, String address) {
		this.id = id;
		this.name = name;
		this.role = role;
		this.address = address;
	}
}

5、控制器 —— EmployeeController.java

@RestController
public class EmployeeController {

    @GetMapping("/employee/records/report")
    public ResponseEntity<byte[]> getEmployeeRecordReport() {
        try {
            // 测试数据
            List<Employee> empLst = createTestData();

            // 报表需要的动态参数
            Map<String, Object> empParams = new HashMap<String, Object>();
            empParams.put("CompanyName", "Spring Boot 整合 JasperReports");
            empParams.put("employeeData", new JRBeanCollectionDataSource(empLst));

            // 编译
            JasperReport jasperReport = JasperCompileManager.compileReport(
                    ResourceUtils.getFile("classpath:employees-details.jrxml").getAbsolutePath()
            );

            // 填充数据
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, empParams, new JREmptyDataSource());

            // 导出报表
            HttpHeaders headers = new HttpHeaders();
            // 设置响应格式:PDF
            headers.setContentType(MediaType.APPLICATION_PDF);
            // 设置文件名称
            headers.setContentDispositionFormData("filename", "employees-details.pdf");
            return new ResponseEntity<byte[]>(JasperExportManager.exportReportToPdf(jasperPrint), headers, HttpStatus.OK);

        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<byte[]>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    private List<Employee> createTestData() {
        List<Employee> resultList = new ArrayList<>();
        resultList.add(new Employee(1, "汪小成", "程序员", "山东省济宁市任城区"));
        resultList.add(new Employee(2, "孙小顺", "部门经理", "安徽省合肥市蜀山区"));
        return resultList;
    }
}

6、查看效果

在谷歌浏览器地址栏输入 http://localhost:9000/employee/records/report 会直接弹出保存文件对话框,实际效果如下:

image-20220615171748450

附录

itext-2.1.7.js8.jar 可以在如下地址下载: jaspersoft.jfrog.io/ui/native/t…