Jasper 不支持在<fieldDescription>
标签中使用参数。
我下载了 Jasper 源代码,但我认为您无法通过简单地实现替代方法来添加此功能XPathExecutor
。原因是因为包含参数的上下文对 XPathExecutor 工厂类不可用。简而言之,需要添加很多上下文传递。
您当然可以尝试添加它,但它会影响许多类文件,然后它会成为 Jasper 可能无法接受的那种更改,并且您将永远合并不同的源。
我不准备冒这个险。另外,我认为 Jasper 迟早会添加这个。
但是,我确实提出了一个解决方案,该解决方案基本上涉及编写您自己的自定义 XPathExecutor,然后通过 Threadlocal 变量实现将上下文传递给它。在下面的示例代码中,Threadlocal 变量是ReportGeneratorJasper.requestContext
static ThreadLocal<ReportRequest> requestContext;
这是在我的班级中设置自定义 XPathExecutor 的代码ReportGeneratorJasper
:
JasperReport repResource = getJasperReport(report);
JasperPrint jp = null;
// Setup for eReports XPATH executers
//
JasperReportsContext jrc = DefaultJasperReportsContext.getInstance();
jrc.setProperty(
JRXPathExecuterUtils.PROPERTY_XPATH_EXECUTER_FACTORY,
XalanNamedParameterXPathExecutor.class.getCanonicalName());
requestContext =
new ThreadLocal<ReportRequest>() {
protected synchronized ReportRequest initialValue() {
return request;
};
};
JasperFillManager jfm = JasperFillManager.getInstance(jrc);
ReportRequest 是我自己的 bean,它包含定义“这个”特定报告生成请求的所有属性。
这是自定义的 XPathExecutor(它也提供了自己的工厂)。:
public class XalanNamedParameterXPathExecutor
extends XalanXPathExecuter implements JRXPathExecuterFactory {
// Reference to the Threadlocal
//
private ReportRequest request;
public static final String PREFIX = "$";
public XalanNamedParameterXPathExecutor() {
this.request = ReportGeneratorJasper.requestContext.get();
}
@Override
public Object selectObject(Node arg0, String xpath) throws JRException {
String useXpath = xpath;
if (xpath.startsWith("$")) {
String value = request.getScalarParamAsString(xpath);
useXpath = (value != null ? value : xpath);
}
return super.selectObject(arg0, useXpath);
}
@Override
public JRXPathExecuter getXPathExecuter() {
return new XalanNamedParameterXPathExecutor();
}
使用 Threadlocal 并不是一个理想的解决方案。如果报表填充器在不同的线程中运行,它很容易中断。但在当前版本的 Jasper 中,这似乎不是问题。
希望 Jasper 将为此实现内置支持。