📄 abstractjasperreportsview.java
字号:
* Finds the report data to use for rendering the report and then invokes the
* <code>renderReport</code> method that should be implemented by the subclass.
* @param model the model map, as passed in for view rendering. Must contain
* a report data value that can be converted to a <code>JRDataSource</code>,
* acccording to the <code>getReportData</code> method.
* @see #getReportData
*/
protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response)
throws Exception {
if (this.subReports != null) {
// Expose sub-reports as model attributes.
model.putAll(this.subReports);
// Transform any collections etc into JRDataSources for sub reports.
if (this.subReportDataKeys != null) {
for (int i = 0; i < this.subReportDataKeys.length; i++) {
String key = this.subReportDataKeys[i];
model.put(key, convertReportData(model.get(key)));
}
}
}
// Expose Spring-managed Locale and MessageSource.
exposeLocalizationContext(model, request);
// Fill the report.
JasperPrint filledReport = fillReport(model);
postProcessReport(filledReport, model);
// Prepare response and render report.
response.reset();
populateHeaders(response);
renderReport(filledReport, model, response);
}
/**
* Expose current Spring-managed Locale and MessageSource to JasperReports i18n
* ($R expressions etc). The MessageSource should only be exposed as JasperReports
* resource bundle if no such bundle is defined in the report itself.
* <p>Default implementation exposes the Spring RequestContext Locale and a
* MessageSourceResourceBundle adapter for the Spring ApplicationContext,
* analogous to the <code>JstlUtils.exposeLocalizationContext</code> method.
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocale
* @see org.springframework.context.support.MessageSourceResourceBundle
* @see #getApplicationContext()
* @see net.sf.jasperreports.engine.JRParameter#REPORT_LOCALE
* @see net.sf.jasperreports.engine.JRParameter#REPORT_RESOURCE_BUNDLE
* @see org.springframework.web.servlet.support.JstlUtils#exposeLocalizationContext
*/
protected void exposeLocalizationContext(Map model, HttpServletRequest request) {
Locale locale = RequestContextUtils.getLocale(request);
model.put(JRParameter.REPORT_LOCALE, locale);
if (this.report.getResourceBundle() == null) {
ResourceBundle bundle = new MessageSourceResourceBundle(getApplicationContext(), locale);
model.put(JRParameter.REPORT_RESOURCE_BUNDLE, bundle);
}
}
/**
* Create a populated <code>JasperPrint</code> instance from the configured
* <code>JasperReport</code> instance.
* <p>By default, thois method will use any <code>JRDataSource</code> instance
* (or wrappable <code>Object</code>) that can be located using {@link #getReportData}.
* If no <code>JRDataSource</code> can be found, this method will use a JDBC
* <code>Connection</code> obtained from the configured <code>javax.sql.DataSource</code>
* (or a DataSource attribute in the model). If no JDBC DataSource can be found
* either, the JasperReports engine will be invoked with plain model Map,
* assuming that the model contains parameters that identify the source
* for report data (e.g. Hibernate or JPA queries).
* @param model the model for this request
* @throws IllegalArgumentException if no <code>JRDataSource</code> can be found
* and no <code>javax.sql.DataSource</code> is supplied
* @throws SQLException if there is an error when populating the report using
* the <code>javax.sql.DataSource</code>
* @throws JRException if there is an error when populating the report using
* a <code>JRDataSource</code>
* @return the populated <code>JasperPrint</code> instance
* @see #getReportData
* @see #setJdbcDataSource
*/
protected JasperPrint fillReport(Map model) throws IllegalArgumentException, SQLException, JRException {
// Determine JRDataSource for main report.
JRDataSource jrDataSource = getReportData(model);
if (jrDataSource != null) {
// Use the JasperReports JRDataSource.
if (logger.isDebugEnabled()) {
logger.debug("Filling report with JRDataSource [" + jrDataSource + "].");
}
return JasperFillManager.fillReport(this.report, model, jrDataSource);
}
else {
if (this.jdbcDataSource == null) {
this.jdbcDataSource = (DataSource) CollectionUtils.findValueOfType(model.values(), DataSource.class);
}
if (this.jdbcDataSource != null) {
// Use the JDBC DataSource.
if (logger.isDebugEnabled()) {
logger.debug("Filling report with JDBC DataSource [" + this.jdbcDataSource + "].");
}
Connection con = this.jdbcDataSource.getConnection();
try {
return JasperFillManager.fillReport(this.report, model, con);
}
finally {
try {
con.close();
}
catch (SQLException ex) {
logger.debug("Could not close JDBC Connection", ex);
}
}
}
else {
// Assume that the model contains parameters that identify
// the source for report data (e.g. Hibernate or JPA queries).
return JasperFillManager.fillReport(this.report, model);
}
}
}
/**
* Populates the headers in the <code>HttpServletResponse</code> with the
* headers supplied by the user.
*/
private void populateHeaders(HttpServletResponse response) {
// Apply the headers to the response.
for (Enumeration en = this.headers.propertyNames(); en.hasMoreElements();) {
String key = (String) en.nextElement();
response.addHeader(key, this.headers.getProperty(key));
}
}
/**
* Find an instance of <code>JRDataSource</code> in the given model map or create an
* appropriate JRDataSource for passed-in report data.
* <p>The default implementation checks for a model object under the
* specified "reportDataKey" first, then falls back to looking for a value
* of type <code>JRDataSource</code>, <code>java.util.Collection</code>,
* object array (in that order).
* @param model the model map, as passed in for view rendering
* @return the <code>JRDataSource</code> or <code>null</code> if the data source is not found
* @see #setReportDataKey
* @see #convertReportData
* @see #getReportDataTypes
*/
protected JRDataSource getReportData(Map model) {
// Try model attribute with specified name.
if (this.reportDataKey != null) {
Object value = model.get(this.reportDataKey);
return convertReportData(value);
}
// Try to find matching attribute, of given prioritized types.
Object value = CollectionUtils.findValueOfType(model.values(), getReportDataTypes());
if (value != null) {
return convertReportData(value);
}
return null;
}
/**
* Convert the given report data value to a <code>JRDataSource</code>.
* <p>The default implementation delegates to <code>JasperReportUtils</code> unless
* the report data value is an instance of <code>JRDataSourceProvider</code>.
* A <code>JRDataSource</code>, <code>JRDataSourceProvider</code>,
* <code>java.util.Collection</code> or object array is detected.
* <code>JRDataSource</code>s are returned as is, whilst <code>JRDataSourceProvider</code>s
* are used to create an instance of <code>JRDataSource</code> which is then returned.
* The latter two are converted to <code>JRBeanCollectionDataSource</code> or
* <code>JRBeanArrayDataSource</code>, respectively.
* @param value the report data value to convert
* @return the JRDataSource
* @throws IllegalArgumentException if the value could not be converted
* @see org.springframework.ui.jasperreports.JasperReportsUtils#convertReportData
* @see net.sf.jasperreports.engine.JRDataSource
* @see net.sf.jasperreports.engine.JRDataSourceProvider
* @see net.sf.jasperreports.engine.data.JRBeanCollectionDataSource
* @see net.sf.jasperreports.engine.data.JRBeanArrayDataSource
*/
protected JRDataSource convertReportData(Object value) throws IllegalArgumentException {
if (value instanceof JRDataSourceProvider) {
try {
return ((JRDataSourceProvider) value).create(this.report);
}
catch (JRException ex) {
throw new IllegalArgumentException("Supplied JRDataSourceProvider is invalid: " + ex);
}
}
else {
return JasperReportsUtils.convertReportData(value);
}
}
/**
* Return the value types that can be converted to a <code>JRDataSource</code>,
* in prioritized order. Should only return types that the
* {@link #convertReportData} method is actually able to convert.
* <p>Default value types are: <code>JRDataSource</code>,
* <code>JRDataSourceProvider</code> <code>java.util.Collection</code>
* and <code>Object</code> array.
* @return the value types in prioritized order
*/
protected Class[] getReportDataTypes() {
return new Class[] {JRDataSource.class, JRDataSourceProvider.class, Collection.class, Object[].class};
}
/**
* Allows sub-classes to get access to the <code>JasperReport</code> instance
* loaded by Spring.
* @return an instance of <code>JasperReport</code>
*/
protected JasperReport getReport() {
return this.report;
}
/**
* Template method to be overridden for custom post-processing of the
* populated report. Invoked after filling but before rendering.
* <p>The default implementation is empty.
* @param populatedReport the populated <code>JasperPrint</code>
* @param model the map containing report parameters
* @throws Exception if post-processing failed
*/
protected void postProcessReport(JasperPrint populatedReport, Map model) throws Exception {
}
/**
* Subclasses should implement this method to perform the actual rendering process.
* <p>Note that the content type has not been set yet: Implementors should build
* a content type String and set it via <code>response.setContentType</code>.
* If necessary, this can include a charset clause for a specific encoding.
* The latter will only be necessary for textual output onto a Writer, and only
* in case of the encoding being specified in the JasperReports exporter parameters.
* <p><b>WARNING:</b> Implementors should not use <code>response.setCharacterEncoding</code>
* unless they are willing to depend on Servlet API 2.4 or higher. Prefer a
* concatenated content type String with a charset clause instead.
* @param populatedReport the populated <code>JasperPrint</code> to render
* @param model the map containing report parameters
* @param response the HTTP response the report should be rendered to
* @throws Exception if rendering failed
* @see #getContentType()
* @see javax.servlet.ServletResponse#setContentType
* @see javax.servlet.ServletResponse#setCharacterEncoding
*/
protected abstract void renderReport(JasperPrint populatedReport, Map model, HttpServletResponse response)
throws Exception;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -