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