abstractjasperreportsview.java

来自「一个关于Spring框架的示例应用程序,简单使用,可以参考.」· Java 代码 · 共 526 行 · 第 1/2 页

JAVA
526
字号
				throw new ApplicationContextException("'reportDataKey' for main report is required when specifying a value for 'subReportDataKeys'");
			}
			this.subReports = new HashMap(this.subReportUrls.size());
			for (Enumeration urls = this.subReportUrls.propertyNames(); urls.hasMoreElements();) {
				String key = (String) urls.nextElement();
				String path = this.subReportUrls.getProperty(key);
				Resource resource = getApplicationContext().getResource(path);
				this.subReports.put(key, loadReport(resource));
			}
		}

		if (this.headers == null) {
			this.headers = new Properties();
		}
		if (!this.headers.containsKey(HEADER_CONTENT_DISPOSITION)) {
			this.headers.setProperty(HEADER_CONTENT_DISPOSITION, CONTENT_DISPOSITION_INLINE);
		}
	}

	/**
	 * Convert the given fully qualified field name to a corresponding
	 * JRExporterParameter instance.
	 *
	 * @param fqFieldName the fully qualified field name, consisting
	 * of the class name followed by a dot followed by the field name
	 * (e.g. "net.sf.jasperreports.engine.export.JRHtmlExporterParameter.IMAGES_URI")
	 * @return the corresponding JRExporterParameter instance
	 */
	protected JRExporterParameter convertToExporterParameter(String fqFieldName) {
		int index = fqFieldName.lastIndexOf('.');
		if (index == -1 || index == fqFieldName.length()) {
			throw new IllegalArgumentException("Parameter name [" + fqFieldName + "] is not a valid static field. " +
					"The parameter name must map to a static field such as " +
					"net.sf.jasperreports.engine.export.JRHtmlExporterParameter.IMAGES_URI");
		}
		String className = fqFieldName.substring(0, index);
		String fieldName = fqFieldName.substring(index + 1);

		try {
			Class cls = ClassUtils.forName(className);
			Field field = cls.getField(fieldName);

			if (JRExporterParameter.class.isAssignableFrom(field.getType())) {
				try {
					return (JRExporterParameter) field.get(null);
				}
				catch (IllegalAccessException ex) {
					throw new IllegalArgumentException("Unable to access field [" + fieldName + "] of class [" + className + "]." +
							" Check that it is static and accessible.");
				}
			}
			else {
				throw new IllegalArgumentException("Field [" + fieldName + "] on class [" + className +
						"] is not assignable from JRExporterParameter - check the type of this field.");
			}
		}
		catch (ClassNotFoundException ex) {
			throw new IllegalArgumentException("Class [" + className + "] in key [" + fqFieldName + "] could not be found.");
		}
		catch (NoSuchFieldException ex) {
			throw new IllegalArgumentException("Field [" + fieldName + "] in key [" + fqFieldName +
					"] could not be found on class [" + className + "].");
		}
	}

	/**
	 * Loads a <code>JasperReport</code> from the specified <code>Resource</code>. If
	 * the <code>Resource</code> points to an uncompiled report design file then the
	 * report file is compiled dynamically and loaded into memory.
	 *
	 * @param resource the <code>Resource</code> containing the report definition or design
	 * @return a <code>JasperReport</code> instance
	 */
	private JasperReport loadReport(Resource resource) throws ApplicationContextException {
		try {
			String fileName = resource.getFilename();
			if (fileName.endsWith(".jasper")) {
				// load pre-compiled report
				if (logger.isInfoEnabled()) {
					logger.info("Loading pre-compiled Jasper Report from " + resource);
				}
				return (JasperReport) JRLoader.loadObject(resource.getInputStream());
			}
			else if (fileName.endsWith(".jrxml")) {
				// compile report on-the-fly
				if (logger.isInfoEnabled()) {
					logger.info("Compiling Jasper Report loaded from " + resource);
				}
				JasperDesign design = JRXmlLoader.load(resource.getInputStream());
				return getReportCompiler().compileReport(design);
			}
			else {
				throw new IllegalArgumentException("Report URL [" + getUrl() + "] must end in either .jasper or .jrxml");
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("Could not load JasperReports report for URL [" + getUrl() + "]", ex);
		}
		catch (JRException ex) {
			throw new ApplicationContextException("Could not parse JasperReports report for URL [" + getUrl() + "]", ex);
		}
	}

	/**
	 * Return the JasperReports compiler to use for compiling a ".jrxml"
	 * file into a a report class. Default is <code>JRBshCompiler</code>,
	 * which requires BeanShell on the class path.
	 *
	 * @see net.sf.jasperreports.engine.design.JRCompiler
	 * @see net.sf.jasperreports.engine.design.JRBshCompiler
	 */
	protected JRCompiler getReportCompiler() {
		return new JRBshCompiler();
	}


	/**
	 * 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 {

		response.setContentType(getContentType());

		// Determine JRDataSource for main report.
		JRDataSource dataSource = getReportData(model);

		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)));
				}
			}
		}

		populateHeaders(response);
		renderReport(this.report, model, dataSource, response);
	}

	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>
	 * @throws IllegalArgumentException if no JRDataSource found
	 * @see #setReportDataKey
	 * @see #convertReportData
	 * @see #getReportDataTypes
	 */
	protected JRDataSource getReportData(Map model) throws IllegalArgumentException {
		// 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);
		}

		throw new IllegalArgumentException("No report data supplied in model " + model);
	}

	/**
	 * 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(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
	 * <code>convertReportData</code> 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
	 * @see #convertReportData
	 */
	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;
	}

	/**
	 * Subclasses should implement this method to perform the actual rendering process.
	 *
	 * @param report the <code>JasperReport</code> to render
	 * @param parameters the map containing report parameters
	 * @param dataSource the <code>JRDataSource</code> containing the report data
	 * @param response the HTTP response the report should be rendered to
	 * @throws Exception if rendering failed
	 */
	protected abstract void renderReport(JasperReport report, Map parameters, JRDataSource dataSource, HttpServletResponse response)
			throws Exception;

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?