DataProviderExtension
DataProviderExtension 让插件以编程方式向平台提供下拉框、lookup 与查询数据。每个 provider 用一个全局唯一的 provider key 注册,返回一组 DataItem(value / label / metadata)。当某个数据需要从多个 model、外部系统或 DSL 无法表达的计算中组合时,可以用 provider 把这套查找逻辑封装在插件内,再由前端按 key 引用。
概念
每个 provider 暴露一个唯一的 provider key,格式为 namespace:provider-name(如 billing:currencies、hr:departments)。平台通过 ExtensionRegistry.getDataProvider(providerKey) 按 getProviderKey() 匹配到对应的 DataProviderExtension,并调用 fetchData(DataRequest) 取数。
DataRequest 携带 provider 取数所需的上下文:
tenantId—— 当前租户searchTerm—— 用户输入的搜索词(下拉框联想用)filters—— 额外的过滤条件 mapoffset/limit—— 分页(默认offset=0、limit=100)pluginId/namespace/providerKey/settings—— 其余上下文
Provider 返回 List<DataItem>,每个 DataItem 是 value(提交值)、label(显示值)与可选的 metadata(附加信息 map)。其结构面向 lookup / 下拉框,而非任意 field-code → value 的行集。
接口签名
package com.auraboot.framework.plugin.extension;
import org.pf4j.ExtensionPoint;
import java.util.List;
import java.util.Map;
public interface DataProviderExtension extends ExtensionPoint {
/** 唯一的 provider key,格式 "namespace:provider-name"。 */
String getProviderKey();
/** 根据请求返回数据项。 */
List<DataItem> fetchData(DataRequest request);
/** 可选:匹配请求的总条数,用于分页(默认取 fetchData 的 size)。 */
default long getCount(DataRequest request) {
return fetchData(request).size();
}
/** 可选:本 provider 是否能处理该 key(默认按 getProviderKey() 比对)。 */
default boolean supports(String providerKey) {
return getProviderKey().equals(providerKey);
}
/** 可选:结果是否可缓存(默认 true)。 */
default boolean isCacheable() { return true; }
/** 可选:缓存 TTL,单位秒(默认 300)。 */
default int getCacheTtlSeconds() { return 300; }
}DataItem 与 DataRequest 是接口内的嵌套 record:
record DataItem(String value, String label, Map<String, Object> metadata) {
DataItem(String value, String label) { this(value, label, Map.of()); }
}
record DataRequest(
Long tenantId, String pluginId, String namespace, String providerKey,
String searchTerm, Map<String, Object> filters,
int offset, int limit, Map<String, Object> settings
) {
static Builder builder() { /* ... */ }
}实现示例
一个返回币种列表的 lookup provider:
package com.acme.billing.provider;
import com.auraboot.framework.plugin.extension.DataProviderExtension;
import org.pf4j.Extension;
import java.util.List;
import java.util.Map;
@Extension
public class CurrencyDataProvider implements DataProviderExtension {
@Override
public String getProviderKey() {
return "billing:currencies";
}
@Override
public List<DataItem> fetchData(DataRequest request) {
return List.of(
new DataItem("usd", "US Dollar", Map.of("symbol", "$")),
new DataItem("eur", "Euro", Map.of("symbol", "€")),
new DataItem("cny", "人民币", Map.of("symbol", "¥"))
);
}
}当下拉框联想时,可读取 request.searchTerm() 过滤;当列表很大时,按 request.offset() / request.limit() 分页并重写 getCount()。
注册
仅需 @Extension 注解 —— 通过 META-INF/extensions.idx 发现,平台启动时由 ExtensionRegistry 收集为 getAllDataProviders()。Provider key 是全局命名空间;请始终带上插件自己的 namespace 前缀以避免冲突(如 billing:currencies 优于裸 currencies)。
常见陷阱
- 返回
null项或null的value/label。 下拉框会渲染异常;缺数据时返回空List更清晰。 - 忽略
getCount()。 lookup 数据量大时请重写它返回真实总数,并在fetchData()中遵守offset/limit,否则分页会错乱。 - 绕过 tenant 作用域。 若查询外部系统或共享数据,请显式按
request.tenantId()限制范围。平台不会替你过滤返回值。 - 在
fetchData()中触发副作用。 该方法会被频繁调用且结果可能被缓存(见isCacheable()/getCacheTtlSeconds())。请保持只读。
相关
- Page Designer —— 在表单/页面中引用 lookup
- 自定义页面 Block —— 自定义 block
- DataAccessor —— 插件读写动态实体数据