携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
主要功能点:
Spring Boot Web 整合 JasperReports,在浏览器地址栏输入访问地址会直接下载 PDF 报表文件;整合过程中遇到的两个比较费时间的问题:
- Maven 依赖包下载失败:Cannot resolve com.lowagie:itext:2.1.7.js8 ;
- 生成的 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 会直接弹出保存文件对话框,实际效果如下:
附录
itext-2.1.7.js8.jar 可以在如下地址下载: jaspersoft.jfrog.io/ui/native/t…