向用户显示报告时,我们的应用程序将提供以下功能:
- 用户将能够选择报告的输出格式。
- 报告视图将是可本地化的,并将以与应用程序用户相同的语言环境输出。
最初设定
为了避免从功能上创建所有CRUD,为简单起见,我将初始化包含将使用SQL脚本显示的值的表。 仅几条记录就足以满足本文的目的,因此,我将使用以下脚本来提供书本表:
insert into book(title, author, published_year, genre, price)
values('The Futurogical Congress', 'Stanislaw Lem', '1978', 'SciFi', 2.5);
insert into book(title, author, published_year, genre, price)
values('Brave New World', 'H. G. Wells', '1975', 'SciFi', 3.99);
insert into book(title, author, published_year, genre, price)
values('Treasure Island', 'Robert Lewis Stevenson', '1948', 'Adventures', 4.45);
insert into book(title, author, published_year, genre, price)
values('The Lord of the Rings', 'J. R. Tolkien', '1945', 'Fantasy', 12.23);
insert into book(title, author, published_year, genre, price)
values('In Cold Blood', 'Truman Capote', '1966', 'Nonfiction', 9.50);
我将创建一个资源包,其中将包含视图和报告的本地化文本。 该文件的名称为Messages.properties ,我将其添加到资源根文件夹下的包net.sf.jasperreports.jsf.sample.usecases中 。 文件内容如下:
report.format.select=Select report format
bookList.pageTitle=Browsing Books
bookList.id=Reference ID
bookList.title=Title
bookList.author=Author
bookList.genre=Genre
bookList.year=Year
bookList.price=Price
我添加了与上一个文件类似的另一个文件,但名为Messages_es.properties并保留了西班牙语翻译,如果您对支持多个以上的语言感兴趣,可以添加其他首选语言。 必须在faces-config.xml文件中配置先前的资源文件:
<faces-config ...>
<application>
<locale-config>
<default-locale>en</default-locale>
<supported-locale>es</supported-locale>
</locale-config>
<resource-bundle>
<var>Messages</var>
<base-name>net.sf.jasperreports.jsf.sample.usecases.Messages</base-name>
</resource-bundle>
</application>
</faces-config>
由于使用的是Maven,因此我将在项目结构中配置一个文件夹来保存报告的.jrxml文件,并配置POM以对该文件夹运行JasperReports编译器。 我选择的文件夹名称是src / main / jasperreports , JasperReports Maven插件的POM配置如下:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jasperreports-maven-plugin</artifactId>
<version>1.0-beta-2</version>
<executions>
<execution>
<goals>
<goal>compile-reports</goal>
</goals>
</execution>
</executions>
<configuration>
<outputDirectory>target/jasperreports/jasper</outputDirectory>
</configuration>
<dependencies>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>4.5.1</version>
</dependency>
</dependencies>
</plugin>
我还将在Maven WAR插件中添加一些额外的配置,以便它可以收集JasperReports编译器生成的所有.jasper文件并将它们打包在应用程序WAR文件中:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<webResources>
<resource>
<directory>src/main/jasperreports</directory>
<includes>
<include>**/*.jrxml</include>
</includes>
<targetPath>resources/reports/sources</targetPath>
</resource>
<resource>
<directory>target/jasperreports/jasper</directory>
<includes>
<include>**/*.jasper</include>
</includes>
<targetPath>resources/reports/jasper</targetPath>
</resource>
</webResources>
</configuration>
</plugin>
您可能会注意到,我将JasperReports的.jrxml文件打包在Web应用程序档案中。 当使用插件时,我们可以将其作为报告模板资源进行引用,插件引擎足够智能,可以识别所引用文件的类型,而当使用对报告源文件的引用时,插件将即时编译报告。 但是,首选方法应该始终是使用.jasper文件,因为它比其他文件具有更好的性能。
设计报告模板
如本系列简介中所述,我将使用的JasperReports视觉设计工具是iReport,那里有很多关于如何使用iReport的教程,因此我将跳过这一部分。 但是,由于我要设计一个可识别语言环境的报告,因此必须注意JasperReports网站上提供的I18n Sample 。
因此,我们启动iReport并选择一个空白报告模板。 由于我们的报告将使用基于SQL的数据源,因此可视设计器完成加载后,我们必须配置SQL语句以从数据库中获取数据。 为此,我们必须在设计器视图中单击缩放选项左侧的按钮,然后选择“报告查询”标签:
我将用来获取数据的SQL查询是我们可以做的最简单的查询。 输入该SQL语句后,iReport将在窗口下部显示所有可用字段。 如果它可以加载所有字段而没有任何错误,则单击“确定”按钮以保存它们以进行报告:
select * from book;
我最终报告中将输出的所有文本都将来自资源包或数据库本身。 因此,正如JasperReports i18n示例所指出的,无论何时要输出一些文本,都应使用文本字段。 报表设计视图将如下图所示:
<?xml version="1.0" encoding="UTF-8"?>
<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="booklist" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20"
topMargin="20" bottomMargin="20">
<property name="ireport.zoom" value="1.5"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<queryString>
<![CDATA[select * from book]]>
</queryString>
<field name="BOOK_ID" class="java.lang.Integer"/>
<field name="TITLE" class="java.lang.String"/>
<field name="AUTHOR" class="java.lang.String"/>
<field name="PUBLISHED_YEAR" class="java.lang.String"/>
<field name="GENRE" class="java.lang.String"/>
<field name="PRICE" class="java.math.BigDecimal"/>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="38" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="227" height="29"/>
<textElement>
<font size="18" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$R{bookList.pageTitle}]]></textFieldExpression>
</textField>
</band>
</title>
<columnHeader>
<band height="27" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="100" height="20"/>
<textElement>
<font isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$R{bookList.id}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="113" y="2" width="155" height="20"/>
<textElement>
<font isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$R{bookList.title}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="285" y="2" width="100" height="20"/>
<textElement>
<font isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$R{bookList.author}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="398" y="2" width="100" height="20"/>
<textElement>
<font isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$R{bookList.year}]]></textFieldExpression>
</textField>
</band>
</columnHeader>
<detail>
<band height="21" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression class="java.lang.Integer"><![CDATA[$F{BOOK_ID}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="113" y="0" width="155" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{TITLE}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="285" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{AUTHOR}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="398" y="0" width="112" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{PUBLISHED_YEAR}]]></textFieldExpression>
</textField>
</band>
</detail>
<columnFooter>
<band height="45" splitType="Stretch"/>
</columnFooter>
<pageFooter>
<band height="25" splitType="Stretch">
<textField>
<reportElement x="227" y="0" width="100" height="20"/>
<textElement textAlignment="Center"/>
<textFieldExpression class="java.lang.Integer"><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
</textField>
</band>
</pageFooter>
<summary>
<band height="42" splitType="Stretch"/>
</summary>
</jasperReport>
将此文件保存在先前创建的src / main / jasperreports文件夹中,您可以开始下一节了。
设计JSF视图
我们的JSF View将基于Facelets ,因此它将被编写为XHTML文件,在其中我们需要声明将要使用的不同库名称空间。 有关如何设置Facelets的说明,请直接转到其文档 (JSF 2.x应用程序无需额外配置即可直接支持Facelets)。
以下代码片段显示了Facelets模板的内容,我将使用它们来呈现图书清单的用户界面。 复制它并将其保存在Web应用程序内容文件中的文件中。 我将使用的文件名为/book/bookList.xhtml :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:jr="http://jasperreportjsf.sf.net/tld/jasperreports-jsf-1_3.tld">
<head>
<title>Book List - JasperReports JSF Use Cases</title>
</head>
<body>
<h1><h:outputText value="#{Messages['bookList.pageTitle']}"/></h1>
<div>
<h:form id="bookListForm">
<jr:source id="bookSource" type="jndi" value="java:comp/env/jdbc/BookStoreDB"/>
<h:panelGrid columns="3">
<h:outputLabel for="reportFormat" value="#{Messages['report.format.select']}" />
<h:selectOneMenu id="reportFormat" value="#{bookList.reportFormat}"
onchange="document.bookListForm.submit();">
<f:selectItems value="#{bookList.reportFormats}" />
</h:selectOneMenu>
<jr:reportLink id="reportLink" format="#{bookList.reportFormat}"
target="blank" source="bookSource"
value="/resources/reports/jasper/booklist.jasper"
resourceBundle="#{Messages}">
<h:outputText value="#{Messages['bookList.action.show']}"/>
</jr:reportLink>
</h:panelGrid>
<h:dataTable value="#{bookList.allBooks}" var="book">
<h:column>
<f:facet name="header">
<h:outputText value="#{Messages['bookList.title']}"/>
</f:facet>
<h:outputText value="#{book.title}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="#{Messages['bookList.author']}"/>
</f:facet>
<h:outputText value="#{book.author}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="#{Messages['bookList.year']}"/>
</f:facet>
<h:outputText value="#{book.publishedYear}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="#{Messages['bookList.genre']}"/>
</f:facet>
<h:outputText value="#{book.genre}"/>
</h:column>
</h:dataTable>
</h:form>
</div>
</body>
</html>
突出显示的行是我们添加JasperReports JSF插件组件的位置:
- 首先,在第14行,我们通过<jr:source>标记定义了一个报告源组件。 该组件不会将任何数据输出到呈现HTML,但是可以由库的可视组件引用,以告诉他们如何获取呈现报表内容所需的数据。
- 从第21行到第26行,我们通过<jr:reportLink>标记定义一个报告链接组件。 该组件将输出一个标准的 HTML元素,该元素指向由插件引擎生成的特殊URL。 当单击它时,插件的引擎将拦截该URL并替换一些JSF生命周期阶段来处理报告数据并生成结果。 注意,报表组件具有一个属性resourceBundle,它指向我们在第一部分中创建的消息包。
注意 : resourceBundle属性已在JasperReports JSF插件的主干版本(在编写此行时)中可用,该版本使用标记库的1.3版本。 对于仍在使用1.2版标记库的用户,他们可以获得类似的结果,将参数添加到报表链接中:
<jr:reportLink id="reportLink" format="#{bookList.reportFormat}"
target="blank" source="bookSource"
value="/resources/reports/jasper/booklist.jasper">
<f:param name="RESOURCE_BUNDLE" value="#{Messages}" />
<h:outputText value="#{Messages['bookList.action.show']}"/>
</jr:reportLink>
除了突出显示的行外,我还添加了代码以呈现一个组合框,其中包含JasperReports JSF插件支持的所有导出选项以及一个数据表,该数据表将为表簿布置不同的记录。
注意 :组合框包含一个onchange属性,该属性旨在使用报表导出选项的新值提交表单。 我必须这样做,才能使报告链接在版本2.x之前的JSF中正常工作,因为该版本不提供任何AJAX支持。
上面显示的JSF视图需要一个托管Bean才能工作,该托管Bean将向用户界面提供值:
public class BookListView {
private BookManager bookManager;
private List allBooks;
private String reportFormat = "pdf";
public void setBookManager(BookManager bookManager) {
this.bookManager = bookManager;
}
public List getAllBooks() {
if (allBooks == null) {
allBooks = bookManager.getAllBooks();
}
return allBooks;
}
public String getReportFormat() {
return reportFormat;
}
public void setReportFormat(String reportFormat) {
this.reportFormat = reportFormat;
}
public List getReportFormats() {
FacesContext context = FacesContext.getCurrentInstance();
JRFacesContext jrContext = JRFacesContext.getInstance(context);
List list = new ArrayList();
for (String format : jrContext.getAvailableExportFormats()) {
list.add(new SelectItem(format, format));
}
return list;
}
}
bookManager字段是对接口的引用,该接口将提供从数据库中获取所有书籍的逻辑:
public interface BookManager {
public List getAllBooks();
}
如本系列的介绍文章中所述,我将不介绍实现用例所需的其他类或接口的细节,因为由每个特定用户来决定哪种框架将提供应用程序的框架。
一起测试
现在该检查所有功能是否正常运行了。 因此,让我们打包我们的Web应用程序,将其部署到我们的Tomcat服务器上,然后在您喜欢的浏览器中输入以下URL: http:// localhost:8080 / jrjsf-usecases / book / bookList.jsf 。
注意 :在执行部署操作之前,Derby(数据库)和Tomcat(应用程序服务器)必须正在运行。
因此,这是我们的浏览器输出前面提到的URL的内容时的外观:
现在,单击“显示报告”链接以查看报告的输出,其中填充了我们资源包中的字符串和数据库中的数据:
这是从报告的PDF视图中截取的示例屏幕截图。 使用用户界面中的组合框可以更改报告导出格式。
结论
因此,完成所有操作,这是向JavaServer Faces应用程序添加报告的最简单方法。 我从一个简单的示例开始,我将不时为其添加更复杂的功能。 希望您喜欢这篇文章并回来以后的出版物,好东西还没有出现!
参考: JasperReports JSF插件用例–来自Code Nibbles博客的JCG合作伙伴 Alonso Dominguez的简单列表报告 。
翻译自: https://www.javacodegeeks.com/2012/07/jasperreports-jsf-plugin-use-cases-2.html