前言
我们在开发插件的过程中,在很多情况下会提供一系列的配置属性,供用户配置,比如:开发一个文件上传到云存储服务器上的插件,我们需要用户自行配置云存储服务器的相关秘钥,而不能直接写死到插件的源代码中。这个时候,我们就需要用到配置类。
在FineReport V10.0/FineBI V5.0中,所有的配置类,都是 com.fr.config.Configuration 的子类,当然在实际使用中,我们通常继承 com.fr.config.DefaultConfiguration即可。
问题
虽然我们通过继承com.fr.config.DefaultConfiguration,实现了插件配置属性的个性化配置(假设为PluginDemoConfig),但是这个时候,我们没有给用户提供一个可视化的操作界面。
用户只能到配置数据库中,找到fine_conf_entity表,添加需要配置的项:
id | value |
---|
PluginDemoConfig.property1 | value1 |
PluginDemoConfig.property2 | 10000 |
之后再重启服务器。
显然这种方式会让使用体验大大的降低,在增加了用户学习成本的同时,也增加了用户维护服务器的成本(每次更改均需重启服务器)。
要解决上面的问题,开发者可以自行开发一个配置界面,用于给用户做可视化的配置属性修改操作,可以使用SystemOptionProvider接口来实现这个,但是这种方式,对于开发者来讲,增加了不少的负担,因为要自己开发web配置界面。
简化方案
为了简化开发者的这部分工作,我们对以下5种基本类型的配置(其他类型暂不支持),提供了内置的设置界面:
类型 |
---|
Integer |
Double |
Boolean |
String |
Long |
开发者只需要在配置属性上加上注解,即可自动在决策平台的系统管理->常规菜单下,进行插件的配置属性查看和修改了,如下图所示:
相关接口
package com.fr.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 用于表示要把一个配置的所有属性暴露在平台参数设置的地方,做统一配置
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Visualization {
/**
* 分类,比如BI参数、运维参数等
* @return 参数分类
*/
String category();
/**
* 展示优先级,默认为0
* @return 优先级
*/
int priority() default 0;
}
package com.fr.config;
import com.fr.stable.StringUtils;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 表明一个配置对象的在某个命名空间下的标识符
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Identifier {
/**
* 配置属性名
*/
String value();
/**
* 属性是否需要展示到配置界面
*/
Status status() default Status.HIDE;
/**
* 该配置是否需要重启后才能生效,默认不需要重启
*/
boolean restart() default false;
/**
* 该配置项的展示名字,可以是一个国际化的key值
*/
String name() default StringUtils.EMPTY;
/**
* 该配置项的描述信息,可以是一个国际化的key值
*/
String description() default StringUtils.EMPTY;
/**
* 该配置项所属的组,比如属于finebi组、report组、core(通用)组,返回值可以作为国际化的key值
*/
String group() default StringUtils.EMPTY;
}
其中注解 com.fr.config.Visualization 用在配置类上,用于标记这个配置类需要在决策平台提供可视化的配置入口,注解 com.fr.config.Identifier 用于标记配置类中各个属性在可视化的配置界面中的描述信息。
使用示例
示例源码:https://code.fanruan.com/fanruan/demo-simple-config
注意事项
因为插件中的配置类要先被使用过,才能被获取到,所以在示例的代码中,在Servlet的Filter初始化的时候,调用了一下配置类。
类型扩展
默认情况下,只提供了5种基本类型的支持,并且默认的配置页面中,只有Boolean是开关,其他4种都是不可以为空的输入框。在实际使用的过程中,我们可能会需要扩展更多的类型以及更丰富的页面设置,比如使用日期或者下拉框等,对此,提供了自定义接口,用户可以自定义类型及对应的处理页面。相关代码教程见:10.0决策平台前端接口
常量中注册组件
BI.config("dec.constant.system.normal.extensible.type", function (items) {
items.push({
value: "java.lang.Date", // 新增的类型
cardType: "dec.system.normal.extensible.date" // 新增类型对应的组件
});
return items;
});
自定义组件
传入的值
对外提供的方法
名称 | 是否必选 | 备注 |
---|
getValue | 是 | 返回当前组件的值,必要的情况下需要对值进行一定的处理 |
validation | 否 | 对当前组件进行有效值校验,返回false不会发送保存请求 |
!(function () {
var ICON_WIDTH = 35, LABEL_WIDTH = 180;
var Date = BI.inherit(BI.Widget, {
props: {
baseCls: "",
value: {}
},
render: function () {
var self = this, v = this.options.value;
return {
type: "bi.vertical_adapt",
items: [{
type: "bi.label",
textAlign: "left",
cls: "dec-font-weight-bold",
text: BI.i18nText(v.name),
width: LABEL_WIDTH
}, {
type: "bi.date_time_combo",
height: 22,
value: v.value,
ref: function (_ref) {
self.timeCombo = _ref;
}
}, {
type: "bi.icon_button",
title: BI.i18nText(v.description),
cls: "detail-font",
width: ICON_WIDTH,
height: 24,
lgap: 116
}]
};
},
getValue: function () {
return this.timeCombo.getValue();
}
});
BI.shortcut("dec.system.normal.extensible.date", Date);
})();