?
This document uses PHP Chinese website manual Release
JasperReports ( http://jasperreports.sourceforge.net ) 是一個(gè)功能強(qiáng)大,開(kāi)源的報(bào)表引擎, 支持使用一種易于理解的XML文檔創(chuàng)建報(bào)表設(shè)計(jì),并可以輸出4種格式的報(bào)表:CSV、Excel、HTML和PDF。
應(yīng)用程序需要包含最新版本的JasperReports(寫(xiě)本文檔的時(shí)候是 0.6.1)。 JasperReports自身依賴(lài)于下面的項(xiàng)目:
BeanShell
Commons BeanUtils
Commons Collections
Commons Digester
Commons Logging
iText
POI
JasperReports還需要一個(gè)JAXP解析器。
要在
ApplicationContext
中配置JasperReports,你必須定義一個(gè)
ViewResolver
來(lái)把視圖名映射到適當(dāng)?shù)囊晥D類(lèi),這取決于你希望輸出什么格式的報(bào)表。
通常,你會(huì)使用ResourceBundleViewResolver
來(lái)根據(jù)一個(gè)屬性文件把視圖名映射到視圖類(lèi)和相關(guān)文件:
<bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver"> <property name="basename" value="views"/> </bean>
這里我們已經(jīng)定義了一個(gè)
ResourceBundleViewResolver
的實(shí)例, 它將通過(guò)基名(base name)
views
在資源文件中查找視圖映射。 這個(gè)文件的詳細(xì)內(nèi)容將在下節(jié)內(nèi)容敘述。
Spring中包含了JasperReports的五種視圖實(shí)現(xiàn),其中四種對(duì)應(yīng)到JasperReports支持的四種輸出格式,另一種支持在運(yùn)行時(shí)確定輸出格式。
表?14.2.?
JasperReports
View
Classes
類(lèi)名 | 渲染格式 |
---|---|
JasperReportsCsvView
|
CSV |
JasperReportsHtmlView
|
HTML |
JasperReportsPdfView
|
|
JasperReportsXlsView
|
Microsoft Excel |
JasperReportsMultiFormatView
|
運(yùn)行時(shí)確定格式(參考
第?14.7.2.4?節(jié) “
使用
JasperReportsMultiFormatView
”
)
|
把這些類(lèi)映射到視圖名和報(bào)表文件只需要簡(jiǎn)單地在前述資源文件中添加適當(dāng)?shù)臈l目。如下:
simpleReport.class=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper
這里你可以看到名為simpleReport
的視圖被映射到JasperReportsPdfView
類(lèi)。 這將產(chǎn)生PDF格式的報(bào)表輸出。該視圖的url屬性被設(shè)置為底層報(bào)表文件的位置。
JasperReports有兩種不同的報(bào)表文件:一種是設(shè)計(jì)文件,以
.jrxml
為擴(kuò)展名;另一種是編譯后的格式,以
.jasper
為擴(kuò)展名。 通常,你使用JasperReports自帶的Ant任務(wù)來(lái)把你的
.jrxml
文件編譯為
.jasper
文件,然后部署到應(yīng)用中。
在Spring里你可以把任一種設(shè)計(jì)文件映射到報(bào)表文件,Spring能幫你自動(dòng)編譯
.jrxml
文件。 但你要注意,
.jrxml
被編譯后即緩存起來(lái)并在整個(gè)應(yīng)用活動(dòng)期間有效,如果你要做一些改動(dòng),就得重啟應(yīng)用。
JasperReportsMultiFormatView
允許在運(yùn)行時(shí)指定報(bào)表格式, 真正解析報(bào)表委托給其它JasperReports的view類(lèi) -
JasperReportsMultiFormatView
類(lèi)簡(jiǎn)單地增加了一層包裝,允許在運(yùn)行時(shí)準(zhǔn)確地指定實(shí)現(xiàn)。
JasperReportsMultiFormatView
類(lèi)引入了兩個(gè)概念:format key和discriminator key。
JasperReportsMultiFormatView
使用mapping key來(lái)查找實(shí)際實(shí)現(xiàn)類(lèi),而使用format key來(lái)查找mapping key。
從編程角度來(lái)說(shuō),你在model中添加一個(gè)條目,以format key作鍵并以mapping key作值,例如:
public ModelAndView handleSimpleReportMulti(HttpServletRequest request, HttpServletResponse response) throws Exception { String uri = request.getRequestURI(); String format = uri.substring(uri.lastIndexOf(".") + 1); Map model = getModel(); model.put("format", format); return new ModelAndView("simpleReportMulti", model); }
在這個(gè)例子中,mapping key由 request URI的擴(kuò)展名來(lái)決定,并以默認(rèn)的format key值
format
加入了model。 如果希望使用不同的format key,你可以使用
JasperReportsMultiFormatView
類(lèi)的formatKey
屬性來(lái)配置它。
JasperReportsMultiFormatView
中默認(rèn)已經(jīng)配置了下列mapping key:
表?14.3.? JasperReportsMultiFormatView默認(rèn)Mapping Key映射
Mapping Key | View Class |
---|---|
csv |
JasperReportsCsvView
|
html |
JasperReportsHtmlView
|
JasperReportsPdfView
|
|
xls |
JasperReportsXlsView
|
所以上例中一個(gè)對(duì)/foo/myReport.pdf的請(qǐng)求將被映射至
JasperReportsPdfView
。 你可以使用
JasperReportsMultiFormatView
的formatMappings
屬性覆蓋mapping key到視圖類(lèi)的映射配置。
為了以你選擇的格式正確地渲染報(bào)表,你必須為Spring提供所有需要的報(bào)表數(shù)據(jù)。
對(duì)JasperReports來(lái)說(shuō),這就是報(bào)表數(shù)據(jù)源(report datasource)和參數(shù)(report
parameters)。 報(bào)表參數(shù)就是一些可以加到model的
Map
中的簡(jiǎn)單鍵值對(duì)。
當(dāng)添加數(shù)據(jù)源到model中時(shí),有兩種選擇。第一種是以任意值為key,添加一個(gè)
JRDataSource
或Collection
到 modelMap
。 Spring將從model中找到它并用作報(bào)表數(shù)據(jù)源。例如,你可能這樣構(gòu)造model:
private Map getModel() { Map model = new HashMap(); Collection beanData = getBeanData(); model.put("myBeanData", beanData); return model; }
第二種方式是以一個(gè)特定鍵值添加
JRDataSource
或Collection
的實(shí)例, 并把該它賦給視圖類(lèi)的
reportDataKey
屬性。 不管哪種方式,Spring都會(huì)把
Collection
實(shí)例轉(zhuǎn)化為
JRBeanCollectionDataSource
實(shí)例。例如:
private Map getModel() { Map model = new HashMap(); Collection beanData = getBeanData(); Collection someData = getSomeData(); model.put("myBeanData", beanData); model.put("someData", someData); return model; }
這里你可以看到有兩個(gè)
Collection
實(shí)例被加到model里。 為了確保使用正確的那個(gè),我們得適當(dāng)?shù)馗膭?dòng)一下視圖的配置:
simpleReport.class=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper simpleReport.reportDataKey=myBeanData
注意當(dāng)使用第一種方式時(shí),Spring將使用它遇到的第一個(gè)
JRDataSource
或
Collection
。 如果你要放置多個(gè)這樣的實(shí)例到model中,你就得使用第二種方式。
JasperReports提供了對(duì)嵌入在主報(bào)表文件中的子報(bào)表的支持。有多種機(jī)制支持在報(bào)表文件中包含子報(bào)表。 最簡(jiǎn)單的方法是在設(shè)計(jì)文件中直接寫(xiě)入子報(bào)表的路徑和SQL查詢。 這種方法的缺點(diǎn)很明顯:相關(guān)信息被硬編碼進(jìn)報(bào)表文件,降低了可復(fù)用性,并使報(bào)表設(shè)計(jì)難以修改。 為了克服這些,你可以聲明式地配置子報(bào)表,并為其包含更多直接來(lái)自controller的數(shù)據(jù)。
使用Spring時(shí),為了控制哪個(gè)子報(bào)表文件被包含,你的報(bào)表文件必須被配置為能夠從外部來(lái)源接受子報(bào)表。 要完成這些你得在報(bào)表文件中聲明一個(gè)參數(shù),像這樣:
<parameter name="ProductsSubReport" class="net.sf.jasperreports.engine.JasperReport"/>
然后,你用這個(gè)參數(shù)定義一個(gè)子報(bào)表:
<subreport> <reportElement isPrintRepeatedValues="false" x="5" y="25" width="325" height="20" isRemoveLineWhenBlank="true" backcolor="#ffcc99"/> <subreportParameter name="City"> <subreportParameterExpression><![CDATA[$F{city}]]></subreportParameterExpression> </subreportParameter> <dataSourceExpression><![CDATA[$P{SubReportData}]]></dataSourceExpression> <subreportExpression class="net.sf.jasperreports.engine.JasperReport"> <![CDATA[$P{ProductsSubReport}]]></subreportExpression> </subreport>
這樣就定義了一個(gè)主報(bào)表文件,接受一個(gè)名為
ProductsSubReport
的參數(shù), 它的值是一個(gè)
net.sf.jasperreports.engine.JasperReports
類(lèi)型實(shí)例。 然后配置Jasper視圖類(lèi)時(shí),你通過(guò)使用
subReportUrls
屬性來(lái)告訴Spring載入一個(gè)報(bào)表文件并作為子報(bào)表傳遞給JasperReports引擎。
<property name="subReportUrls"> <map> <entry key="ProductsSubReport" value="/WEB-INF/reports/subReportChild.jrxml"/> </map> </property>
這里Map
中的key對(duì)應(yīng)于報(bào)表設(shè)計(jì)文件中子報(bào)表參數(shù)的名字,它的值代表子報(bào)表文件的URL。
Spring將載入該文件,需要的話進(jìn)行編譯,然后以給定的key為參數(shù)名傳遞給JasperReports引擎。
當(dāng)使用Spring配置子報(bào)表時(shí),這一步完全是可選的。如果你喜歡,仍可以使用靜態(tài)查詢作為子報(bào)表的數(shù)據(jù)源。
然而,如果你希望Spring把你返回的
ModelAndView
中的數(shù)據(jù)轉(zhuǎn)化為
JRDataSource
, 你就得告訴Spring
ModelAndView
中的那個(gè)參數(shù)需要被轉(zhuǎn)化。 實(shí)際操作時(shí),你需要使用所選視圖類(lèi)的
subReportDataKeys
屬性,為其配置一個(gè)參數(shù)名列表:
<property name="subReportDataKeys" value="SubReportData"/>
這里提供的key值必須與ModelAndView
和報(bào)表設(shè)計(jì)文件中使用的key值對(duì)應(yīng)。
如果你對(duì)exporter的配置有特殊要求,比如你可能要求特定頁(yè)面尺寸的PDF報(bào)表,
那你可以在Spring配置文件中聲明式地配置這些,通過(guò)使用視圖類(lèi)的
exporterParameters
屬性, 該屬性是Map
型值,其中的key應(yīng)該是一個(gè)代表exporter參數(shù)定義的靜態(tài)域的全限定名,value是要賦給參數(shù)的值。
示例如下:
<bean id="htmlReport" class="org.springframework.web.servlet.view.jasperreports.JasperReportsHtmlView"> <property name="url" value="/WEB-INF/reports/simpleReport.jrxml"/> <property name="exporterParameters"> <map> <entry key="net.sf.jasperreports.engine.export.JRHtmlExporterParameter.HTML_FOOTER"> <value>Footer by Spring! </td><td width="50%">&nbsp; </td></tr> </table></body></html> </value> </entry> </map> </property> </bean>
這里你可以看到,我們?yōu)? JasperReportsHtmlView
配置了一個(gè)exporter參數(shù), 參數(shù)
net.sf.jasperreports.engine.export.JRHtmlExporterParameter.HTML_FOOTER
定義了結(jié)果HTML中的頁(yè)腳。