您的位置:首页 > 编程语言 > ASP

Working with JasperReports for easy report generation

2016-06-17 16:14 671 查看
转自:http://www.jcombat.com/spring/working-with-jasperreports-for-easy-report-generation

JasperReports is a Java
based open source report generating engine. It has great dynamic report generating capabilities that can be added to any Java based application. I have a very simple demo to show how it works.
I have created a link somewhere in my application and on the click of it, I see a pop-up window with the report PDF embedded within.
To start with, we need a .jrxml template
that is externalized and every time the link is clicked, the.jrxml template
is dynamically compiled to generate a .jasper file
at the same external file location. So the first and foremost step is to prepare the mark-up for the report template, which can be easily designed using the iReport tool. The tool finally generates the .jrxml file
based on the design. The standard JasperReport template has the following layout in the same order:

1234567<title><pageHeader><columnHeader><detail><columnFooter><pageFooter><summary>
Fine, now let’s assume, I have my .jrxml file generated and looks something like:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

<!DOCTYPE
jasperReport PUBLIC "//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<jasperReport
xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="jasper_report_template"
language="groovy"
pageWidth="595"
pageHeight="842"
columnWidth="555"
leftMargin="20"
rightMargin="20"
topMargin="20"
bottomMargin="20"
xmlns="http://jasperreports.sourceforge.net/jasperreports"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<parameter
name="ReportTitle"
class="java.lang.String"/>

<parameter
name="Author"
class="java.lang.String"/>

<queryString></queryString>

<field
name="subjectName"
class="java.lang.String">

<fieldDescription>subjectName</fieldDescription>

</field>

<field
name="marks"
class="java.math.BigDecimal">

<fieldDescription>marks</fieldDescription>

</field>

<title>

<band
height="70">

<line>

<reportElement
x="0"
y="0"
width="515"
height="1"/>

</line>

<textField
isBlankWhenNull="true"
bookmarkLevel="1">

<reportElement
x="0"
y="10"
width="515"
height="30"/>

<textElement
textAlignment="Center">

<font
size="22"/>

</textElement>

<textFieldExpression
class="java.lang.String">$P{ReportTitle}</textFieldExpression>

<anchorNameExpression>"Title"</anchorNameExpression>

</textField>

<textField
isBlankWhenNull="true">

<reportElement
x="0"
y="40"
width="515"
height="20"/>

<textElement
textAlignment="Center">

<font
size="10"/>

</textElement>

<textFieldExpression
class="java.lang.String">$P{Author}</textFieldExpression>

</textField>

</band>

</title>

<columnHeader>

<band
height="23">

<staticText>

<reportElement
mode="Opaque"
x="0"
y="3"
width="535"
height="15"
backcolor="#70A9A9"/>

<box>

<bottomPen
lineWidth="1.0"
lineColor="#CCCCCC"/>

</box>

<textElement/>

<text></text>

</staticText>

<staticText>

<reportElement
x="414"
y="3"
width="121"
height="15"/>

<textElement
textAlignment="Center"
verticalAlignment="Middle">

<font
isBold="true"/>

</textElement>

<text>Marks</text>

</staticText>

<staticText>

<reportElement
x="0"
y="3"
width="136"
height="15"/>

<textElement
textAlignment="Center"
verticalAlignment="Middle">

<font
isBold="true"/>

</textElement>

<text>Subject</text>

</staticText>

</band>

</columnHeader>

<detail>

<band
height="16">

<staticText>

<reportElement
mode="Opaque"
x="0"
y="0"
width="535"
height="14"
backcolor="#E5ECF9"/>

<box>

<bottomPen
lineWidth="0.25"
lineColor="#CCCCCC"/>

</box>

<textElement/>

<text></text>

</staticText>

<textField>

<reportElement
x="414"
y="0"
width="121"
height="15"/>

<textElement
textAlignment="Center"
verticalAlignment="Middle">

<font
size="9"/>

</textElement>

<textFieldExpression
class="java.lang.String">$F{subjectName}</textFieldExpression>

</textField>

<textField>

<reportElement
x="0"
y="0"
width="136"
height="15"/>

<textElement
textAlignment="Center"
verticalAlignment="Middle"/>

<textFieldExpression
class="java.lang.String">$F{marks}</textFieldExpression>

</textField>

</band>

</detail>

<columnFooter>

<band
height="200">

<barChart>

<chart
evaluationTime="Report">

<reportElement
x="0"
y="0"
width="555"
height="200"/>

<chartTitle>

<titleExpression>"My
First JR Bar Chart"</titleExpression>

</chartTitle>

</chart>

<categoryDataset>

<dataset
incrementType="None"/>

<categorySeries>

<seriesExpression>$F{subjectName}</seriesExpression>

<categoryExpression>$F{subjectName}</categoryExpression>

<valueExpression>$F{marks}</valueExpression>

</categorySeries>

</categoryDataset>

<barPlot
isShowTickMarks="false">

<plot/>

</barPlot>

</barChart>

</band>

</columnFooter>

<pageFooter>

<band
height="400"
splitType="Stretch">

<pieChart>

<chart
evaluationTime="Report">

<reportElement
x="135"
y="0"
width="270"
height="300"/>

<chartTitle>

<titleExpression>"My
First JR Pie Chart"</titleExpression>

</chartTitle>

</chart>

<pieDataset>

<dataset
incrementType="None"/>

<keyExpression>$F{subjectName}</keyExpression>

<valueExpression>$F{marks}</valueExpression>

</pieDataset>

<piePlot>

<plot/>

<itemLabel/>

</piePlot>

</pieChart>

</band>

</pageFooter>

</jasperReport>

I keep the above .jrxml file
to some externalised location, let it be, D:/Documents/

Create a sample POJO, with two instance variables for subject name and marks, as:
DataMarksBean.java

12345678910111213141516171819202122package com.jcombat.beans; public class DataMarksBean { private String subjectName; private Integer marks; public String getSubjectName() { return subjectName; } public void setSubjectName(String subjectName) { this.subjectName = subjectName; } public Integer getMarks() { return marks; } public void setMarks(Integer marks) { this.marks = marks; }}
Create another class DataBeanMarksList.java, which generates a collection of java bean objects to be used for report generation. This class looks something like:DataBeanMarksList.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

package
com.jcombat.bo;

import
java.util.ArrayList;

public
class
DataBeanMarksList
{

public
ArrayList<DataMarksBean>
getDataBeanList()
{

ArrayList<DataMarksBean>
dataBeanList
=
new
ArrayList<DataMarksBean>();

dataBeanList.add(produce("English",
58));

dataBeanList.add(produce("SocialStudies",
68));

dataBeanList.add(produce("Maths",
38));

dataBeanList.add(produce("Hindi",
88));

dataBeanList.add(produce("Scince",
78));

return
dataBeanList;

}

/*

*
This method returns a DataBean object, with subjectName and marks set

*
in it.

*/

private
DataMarksBean
produce(String
subjectName,
Integer
marks)
{

DataMarksBean
dataBean
=
new
DataMarksBean();

dataBean.setSubjectName(subjectName);

dataBean.setMarks(marks);

return
dataBean;

}

}

Now you need to create a method in the controller of your Spring MVC application, that actually serves the purpose of report generation. I give it some mapping as /jasper

123456789101112131415161718192021222324252627282930313233343536373839@RequestMapping(value = "/jasper")public void generatePDFJasperChart(HttpServletRequest request, HttpServletResponse response) throws IOException { String sourceFileName = "D://Documents/jasper_report_template.jrxml"; System.out.println(sourceFileName); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("ReportTitle", "Jasper Demo"); parameters.put("Author", "Prepared By jCombat"); try { System.out.println("Start compiling!!! ..."); JasperCompileManager.compileReportToFile(sourceFileName); System.out.println("Done compiling!!! ..."); sourceFileName = "D://Documents/jasper_report_template.jasper"; DataBeanMarksList DataBeanList = new DataBeanMarksList(); ArrayList<DataMarksBean> dataList = DataBeanList.getDataBeanList(); JRBeanCollectionDataSource beanColDataSource = new JRBeanCollectionDataSource( dataList); JasperReport report = (JasperReport) JRLoader .loadObjectFromFile(sourceFileName); JasperPrint jasperPrint = JasperFillManager.fillReport(report, parameters, beanColDataSource); if (jasperPrint != null) { byte[] pdfReport = JasperExportManager .exportReportToPdf(jasperPrint); response.reset(); response.setContentType("application/pdf"); response.setHeader("Cache-Control", "no-store"); response.setHeader("Cache-Control", "private"); response.setHeader("Pragma", "no-store"); response.setContentLength(pdfReport.length); response.getOutputStream().write(pdfReport); response.getOutputStream().flush(); response.getOutputStream().close(); } } catch (JRException e) { e.printStackTrace(); }}
Almost done, create a link somewhere on the landing page in your application as:

1

<a
href=""
onclick="openNewWindowForJasperWithCharts();">Generate
Report</a>

Male sure you include the following javascript function as well into your application:

12345function openNewWindowForJasperWithCharts(){ var url = "/jasper"; var strWindowFeatures = "menubar=no,location=no,width=800,height=500"; window.open(url,"_blank", "location=0,height=500,width=800");}
Finally, clicking on the link, shows up the report PDF in a new pop-up window as:

If you need the same report to be exported to HTML, just modify the above controller method and add the following:

1

2

3

if
(jasperPrint
!=
null)
{

renderHtml(new
JRHtmlExporter(),
jasperPrint,
writer);

}

Add a new method renderHtml as:

1

2

3

4

5

6

7

8

public
static
void
renderHtml(JRExporter
exporter,
JasperPrint
print,
Writer
writer)

throws
JRException
{

exporter.setParameter(JRExporterParameter.JASPER_PRINT,
print);

exporter.setParameter(JRExporterParameter.OUTPUT_WRITER,
writer);

exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN,
Boolean.FALSE);

exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI,
"servlets/image?image=");

exporter.exportReport();

}

So we have several points worth noting:

The .jasper file is not kept
anywhere in the JVM for any subsequent PDF generation and for now, is generated every time the link is clicked.

As expected, if we modify the .jrxml template,
it reflects instantly at runtime and we do not require any java changes, hence no build/deploy needed.

As per the documentation available for JasperReports, “Even though all its reporting functionality is available in this single JAR file (jasperreports-5.0.1.jar),
JasperReports relies on other third-party libraries for related required functionality like XML parsing, logging, and PDF generation.”

To avoid performance hit on the application because of the .jrxml file
being compiled again and again, I suggest following options to restrict the subsequent compilations:

We can keep the .jasper file in cache and
generate the .jasper soon after
the cache expires.

We can also check for the existing .jasper file
at the respective externalized location. If it doesn’t exist, compile, else not.

We can build a utility to explicitly compile the .jrxml template,
generate the .jasper file and
copy it to the respective externalized location.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: