我正在开发一个旨在用JasperReports Server替换当前PDF生成器的项目。计划是使用REST / HTTP API在系统之间实现高级抽象。
最理想的是,我们不希望让JasperReports Server从数据库中提取数据,因为这会绕过调用应用程序架构中的现有日志记录和授权。相反,我们首先要在调用应用程序中提取内容,然后将该内容传递给JasperReports Server。
我们已经做了相当多的调查,缺乏相关结果表明这不是您通常使用JasperReports Server的方式。我们发现的教程中的输入参数通常是标量值(整数,布尔值或字符串),而不是复杂的结构或对象。此外,似乎每个样本或多或少都假设您希望让JasperReports Server连接到数据库。
如果可以传递复杂的结构(比如一组地图,其中一些地图元素是数组或地图本身),那么这样做的最佳做法是什么?我不知道如何在请求体中格式化这样的结构。 SOAP API更适合吗?
如果您根本不设计JasperReports Server解决方案,那么哪种替代产品/解决方案更合适?
提前感谢任何输入。
答案 0 :(得分:8)
经过几个小时的研究,我想我已经准备好回答我自己的问题。
JasperReports Server(下面的“JRS”)基本上是为自己获取数据而设计的。虽然可以强制向JRS提供数据,但我决定不这样做。
不让JRS获取数据本身的一个最明显的缺点是,不再可能从JRS Web界面生成报告。如果客户端应用程序负责以预定义的格式提供数据,那么与其他系统的集成也变得不可能或困难。
在我正在开发的项目中,我们决定构建一个基于Remote XML DataSource的自定义JRS DataSource,它调用客户端应用程序的XML API。换句话说,客户端应用程序从JRS请求报告,然后JRS从客户端应用程序请求它的数据。我们必须扩展XML API以满足我们的所有报告需求,但在我看来这是一件好事。良好的API覆盖将在未来派上用场。
我希望这些想法可以帮助有类似问题的人。
答案 1 :(得分:0)
正如您所写,获取数据是JRS更自然的方式。但是,我需要采取相反的方式 - 我通过REST调用POST数据来报告坐在JRS回购中。
我在参数“xmlDocument”中传递XML数据,并且通过“技巧”,执行的报告可以使用此XML进行进一步的X路径查询。
xmlDocument只是一个简单的字符串:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
在设计阶段,我使用我用于预览的XML文件创建XML数据适配器。请注意,选择XML适配器后会出现一个新参数XML_INPUT_STREAM。
然后我将报告发布到JRS。 在报告执行期间,当报告未链接到任何数据源时,它会读取XML_INPUT_STREAM参数(作为回退数据源),如下所示:
<parameter name="xmlDocument" class="java.lang.String">
<defaultValueExpression><![CDATA["<?xml version=\"1.0\" encoding=\"UTF-8\"?><documentData></documentData>"]]></defaultValueExpression>
</parameter>
我将“xmlDocument”字符串包装到InputStream。
答案 2 :(得分:0)
即使我同意答案,但女巫指出JasperServer本身就是为了获取数据而构建的,我仍然必须通过其余API传递数据,因为这是我公司构建Jasper报告的传统方式,并且我们要使用自定义Java服务来获取数据。
具有要传递给报告槽Web API的简单自定义pojo:
public class CustomReport {
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public CustomReport() {
super();
}
1)定义必须在服务器上部署的自定义jasper scriptlet,作为与报表相关的资源,女巫将使用GSON将字符串反序列化为自定义pojo对象:
public class CustomScriptlet
extends JRDefaultScriptlet { public void afterReportInit()
throws JRScriptletException
{
Object customSerializedObj = getParameterValue("customSerialized");
if (customSerializedObj != null)
{
String customSerializedStr = customSerializedObj.toString();
if ((customSerializedStr != null) && (customSerializedStr.length() > 0))
{
CustomReport customReport = new Gson().fromJson(customSerializedStr,
CustomReport.class);
setVariableValue("customReport", customReport);
}
}
}
2)在jasper服务器中的自定义scriptlet中使用参数/变量:
<scriptlet name="Scriptlet_1" class="eu.dedalus.jasper.api.scriptlet.CustomScriptlet">
<scriptletDescription><![CDATA[CustomScriptlet]]></scriptletDescription>
</scriptlet>
<parameter name="customSerialized" class="java.lang.String"/>
<variable name="customReport" class="com.test.CustomReport" calculation="System"/>
3)像这样调用API @ jasperserver / rest_v2 / reportExecution:
"reportUnitUri" : "/report/Custom_report",
"async":"false",
"outputFormat":"pdf",
"parameters" : {
"reportParameter" : [
{
"name": "customReport",
"value": ["{ \"content\" : \"test content\" } "]
}
]
}