【仅供内部供应商使用,不提供对外解答和培训】
Table of Contents |
---|
低版本产品 : 下文中的低版本产品特指FineReport10.0以下的版本
报表预览:下文中特指cpt/frm模板的预览方式,但不包含移动端预览和H5预览方式。
无
标准的帆软报表产品中只支持基于标准JDBC或JNDI的数据查询和几种基础的文件数据。对于非标JDBC数据库、WebService、REST、实时库、RPC等等的数据接口系统的对接需要依赖数据集接口接入。
以往开发者大多都接触过程序数据集的基本实现方法,程序数据集从功能上是可以满足开发者对数据的绝大部分诉求的,不过对于报表制作人员来说,程序数据集存在叫非常明显的短板就是,使用并不友好。制作人员需要记住大量的类名和业务的关联关系,或者需要手动添加大量的参数实现“配置化”的基本实现方法。程序数据集从功能上是可以满足开发者对数据的绝大部分诉求的。不过对于报表制作人员来说,程序数据集存在叫非常明显的短板就是使用并不友好。制作人员需要记住大量的类名和业务的关联关系,或者需要手动添加大量的参数实现“配置化”,但是又无法解决参数配置化导致的参数引入问题(比如某些敏感配置只能在制作模板的时候指定,禁止从URL/参数面板等地方引入)。为了给报表制作人员提供更好的使用体验和安全体验,产品内设计了TableDataDefineProvider接口,让开发者得以用插件的形式向用户提供数据集扩展。
...
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
package com.fr.design.fun;
import com.fr.base.TableData;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.stable.fun.mark.Mutable;
import com.fr.stable.fun.mark.Aftermath;
/**
* @author : richie
* @since : 7.1.1
* 自定义报表数据集界面接口,单独存在的一个个数据集
*/
public interface TableDataDefineProvider extends Mutable, Aftermath {
String XML_TAG = "TableDataDefineProvider";
int CURRENT_LEVEL = 1;
/**
* 自定义的数据集设置界面所对应的数据集类型
* @return 数据集的类型
*/
Class<? extends TableData> classForTableData();
/**
* 自定义数据集设置界面所对应的初始化数据集类型,在一种数据集有多个实现的时候有效
* @return 数据集类型
*/
Class<? extends TableData> classForInitTableData();
/**
* 自定义的数据集设置界面所对应的界面类型
* @return 数据集界面类型
*/
Class<? extends AbstractTableDataPane> appearanceForTableData();
/**
* 自定义数据集设置界面在菜单上的现实名字
* @return 名字
*/
String nameForTableData();
/**
* 自定义数据集在新建的时候名字前缀
* @return 名字前缀
*/
String prefixForTableData();
/**
* 自定义数据集在菜单上现实的图标
* @return 图标
*/
String iconPathForTableData();
}
|
Code Block | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||
/**
*
*/
package com.fr.base;
import com.fr.config.utils.UniqueKey;
import com.fr.data.TableDataSource;
import com.fr.data.impl.DataCacheKey;
import com.fr.data.impl.ParameterCacheKey;
import com.fr.general.data.DataModel;
import com.fr.script.Calculator;
import com.fr.stable.ParameterProvider;
import java.util.ArrayList;
/**
* @date: 2014-11-24-上午11:30:22
*/
public abstract class AbstractTableData extends UniqueKey implements TableData {
/**
* 克隆
*
* @return 克隆的数据集
* @throws CloneNotSupportedException
* @date 2014-11-24-上午11:56:19
*/
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
/**
* 获取当前tabledata所有的列名
*
* @param datasource 当前数据源
* @return 所有列名的数组
* @date 2014-11-24-上午11:49:07
*/
public String[] getColumnNames(TableDataSource datasource) {
return new String[0];
}
/**
* 获取没有权限访问的数据集列表
*
* @param toBeRemoveList 没有权限的列表
* @param nameWillBeRemove 需要移除的对象
* @param name 当前数据集名
* @date 2014-11-24-下午3:58:29
*/
public void registerNoPrivilege(ArrayList<String> toBeRemoveList, String nameWillBeRemove, String name) {
}
/**
* @param calculator 连接上下文计算的算子
* @param timeoutSeconds 超时单位:秒
* @return
*/
public DataModel createDataModelWithTimeout(Calculator calculator, int timeoutSeconds) {
return createDataModel(calculator);
}
public void setParameters(ParameterProvider[] paras) {
}
public void filterDataType(Class<?> type) {
}
@Override
public DataCacheKey getDataCacheKey(Calculator calculator) {
return new ParameterCacheKey(Calculator.processParameters(calculator, getParameters(calculator)));
}
}
|
Code Block | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||
/* * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. */ package com.fr.data; import com.fr.base.AbstractTableData; import com.fr.config.holder.factory.XmlHolders; import com.fr.config.holder.impl.xml.XmlColConf; import com.fr.general.ComparatorUtils; import com.fr.general.data.DataModel; import com.fr.script.Calculator; import com.fr.stable.ArrayUtils; import com.fr.stable.ParameterProvider; import com.fr.stable.script.CalculatorKey; import com.fr.stable.xml.StableXMLUtils; import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLReadable; import com.fr.stable.xml.XMLableReader; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * 带参数的数据集的抽象实现,如果需要设计一个带参数的数据集,可以继承此类以简化代码 */ public abstract class AbstractParameterTableData extends AbstractTableData { private static final long serialVersionUID = 7017455818551821178L; public static final CalculatorKey ROW_COUNT = CalculatorKey.createKey("rowCount"); //动态Parameter. //参数数组. protected XmlColConf<Collection<ParameterProvider>> parameters = XmlHolders.collection(new ArrayList<ParameterProvider>(),ParameterProvider.class); /** * 获取数据集所使用的参数 * * @param c 算子 * @return 参数数组 */ public ParameterProvider[] getParameters(Calculator c) { Collection<ParameterProvider> value = this.parameters.get(); return value.size() == 0 ? processParameters(c) : value.toArray(new ParameterProvider[value.size()]); } @Override public void setParameters(ParameterProvider[] parameters) { this.parameters.set(ArrayUtils.toList(parameters)); } /** * 设置参数 * * @param providers 参数 */ protected void setDefaultParameters(ParameterProvider[] providers) { this.parameters.set(ArrayUtils.toList(providers)); } /** * 将数据集中的${p1}形式的参数解析成运行时的参数值 * * @param calculator 连接上下文运算的算子 * @return 解析后的参数数组,可以通过获取公式的结果获取解析后的值 */ protected ParameterProvider[] processParameters(Calculator calculator) { Collection<ParameterProvider> parameterProviders = this.parameters.get(); return Calculator.processParameters(calculator, parameterProviders.toArray(new ParameterProvider[parameterProviders.size()])); } public void readXML(XMLableReader reader) { if (reader.isChildNode()) { String tmpName = reader.getTagName(); if (ParameterProvider.ARRAY_XML_TAG.equals(tmpName)) {//读取Parameters. final List tmpParameterList = new ArrayList(); reader.readXMLObject(new XMLReadable() { public void readXML(XMLableReader reader) { if (ParameterProvider.XML_TAG.equals(reader.getTagName())) { tmpParameterList.add(StableXMLUtils.readParameter(reader)); } } }); //转换数组. if (!tmpParameterList.isEmpty()) { this.parameters.set(tmpParameterList); } } } } public void writeXML(XMLPrintWriter writer) { //保存parameters. Collection<ParameterProvider> providers = this.parameters.get(); StableXMLUtils.writeParameters(writer, providers.toArray(new ParameterProvider[providers.size()])); } public boolean equals(Object obj) { return obj instanceof AbstractParameterTableData && ComparatorUtils.equals(this.parameters, ((AbstractParameterTableData) obj).parameters); } /** * 克隆 * * @return 克隆的数据集 * @throws CloneNotSupportedException */ @SuppressWarnings("unchecked") public Object clone() throws CloneNotSupportedException { AbstractParameterTableData cloned = (AbstractParameterTableData) super.clone(); cloned.parameters = (XmlColConf<Collection<ParameterProvider>>) this.parameters.clone(); return cloned; } /** * 创建数据集 * * @param calculator 连接上下文计算的算子 * @param name 数据集的名字 * @return 返回数据集 */ public DataModel createDataModel(Calculator calculator, String name) { return createDataModel(calculator); } /** * 创建数据集 * * @param calculator 连接上下文计算的算子 * @param rowCount 要获取数据的行数 * @return 返回数据集 */ public DataModel createDataModel(Calculator calculator, int rowCount) { calculator.setAttribute(AbstractParameterTableData.ROW_COUNT, rowCount); return createDataModel(calculator); } } |
产品线 | 版本 | 支持情况 | 备注 |
---|---|---|---|
FR | 8.0 | 支持 | |
FR | 9.0 | 支持 | |
FR | 10.0 | 支持 | |
BI | 3.6 | 支持 | |
BI | 4.0 | 支持 | |
BI | 5.1 | 支持 | |
BI | 5.1.2 | 支持 | |
BI | 5.1.3 | 支持 |
...
classForTableData: 接口需要返回一个TableData接口类。实际开发时为了方便开发提高效率和稳定性,要求开发者全部继承AbstractParameterTableData[注意点]
classForInitTableData:这个接口如果已经实现了classForTableData的话,目前没有什么实质性的作用,不过一般要求开发者保留性的与classForTableData返回相同的class。在实现AbstractParameterTableData接口时,固定需要实现createDataModel方法。如果有其他自定义配置则需要额外实现readXML/writeXML两个接口方法,且自定义配置需要符合配置文件接口开发标准(必须是Conf对象,具体见demo示例)
demo地址:demo-table-data-define
...