天行有常,不为尧存,不为桀亡。——荀子《天论》
本文用于描述业务层的其中另一个核心配置:字典配置(dict)。
dict 的配置位于
I_SERVICE
表中(zero-jet)
参数字段 | 类型 | 说明 |
---|---|---|
dictConfig | 字符串(JsonArray格式) | dict 字典定义配置 |
dictComponent | 字符串(Java类) | dict 的自定义组件 |
dictEpsilon | 字符串(JsonObject格式) | dict 字典的消费字段配置 |
dictEpsilon 的消费字段配置仅使用左值(平台内的)字段名,不使用任何第三方的配置字段名。
dictConfig
中配置了当前通道组件需要使用的所有字典信息,目前不支持延迟加载模式,它的格式如下:
[
{
"source": "TABULAR",
"types": [
"ci.environment",
"ci.status",
"ci.approval.status",
"remove.mode",
"add.mode",
"level.info.system",
"level.protect"
]
},
{
"source": "CATEGORY",
"types": [
"ci.type"
]
},
{
"source": "ASSIST",
"key": "ci.relation.mapping",
"component": "cn.originx.ucmdb.plugin.tunnel.DictRelationDef"
}
]
dict 的配置依赖四个核心的 Zero 类:
io.vertx.up.commune.config.Dict
:(定义)对应该配置的核心字典定义。io.vertx.up.commune.config.DictSource
:(定义)对应该配置中的每一个元素(JsonObject)的定义。io.vertx.up.commune.config.DictEpsilon
:(定义)对应某一个字段的消费定义。io.vertx.up.commune.config.DictFabric
:字典翻译器,根据字典翻译当前的数据专用执行器。dictConfig 是一个JsonArray的字符串,定义了所有当前通道需要使用的字典,主要分为:标准字典 和 扩展字典两种,而标准字典中又包含了平行列表和树形列表,整个字典定义最终会转换成数据结构:ConcurrentMap<String,JsonArray>
来存储字典数据。每个字典的属性定义如下:
属性名 | 支持 | 说明 |
---|---|---|
source | 标准字典 / 扩展字典 | 字典类型 |
types | 标准字典 | 标准字典中的types的每一个元素会转换成上述数据结构中的键 |
key | 扩展字典 | 单个元素转换成上述数据结构中的键 |
component | 扩展字典 | Java类名,所有扩展字典需要提供该类,该类实现接口:DictionaryPlugin |
X_TABULAR
中的 type
字段。X_CATEGORY
中的 type
字段。字典组件规范
io.vertx.tp.optic.component.Dictionary
接口。io.vertx.tp.optic.business.ExAmbientDictionary
类。Dictionary
的实现类对应到 dictConfig 的整体配置中,为一个 JsonArray
格式,表示多个字典,而该类内部调用了:io.vertx.tp.optic.component.DictionaryPlugin
插件,该插件用于处理某一个字典来源信息(只针对ASSIST)。在字典扩展中,主要包含两层:
DictionaryPlugin
扩展,配置到 ASSIST
类型的字典中。Dictionary
类,直接从该类扩展。该字段为字典消费配置,格式如:
{
"status": {
"source": "ci.status",
"in": "name",
"out": "key"
},
"environment": {
"source": "ci.environment",
"in": "name",
"out": "key"
}
]
上述片段定义了模型中两个字段的消费信息:
status
字段消费名为ci.status
的字典信息,传入数据为字典元素对象的name
字段的值,当前对应字段为key字段
。environment
字段消费名为ci.environment
的字典信息(出入配置同上)。上述配置中,status
和environment
均为当前模型的字段信息,它可以是
配置名 | 说明 |
---|---|
source | 字典名称,对应到 dictConfig 中生成的ConcurrentMap<String,JsonArray>数据结构中的键值。 |
in | 第三方的传入值对应的字典字段名。 |
out | Ox平台的最终翻译存储值。 |
字典配置中的终点是开发者需要理解如何使用:DictFabric
类,它有两种模式:
DualItem
的映射配置,这种情况只能翻译平台内的属性。DualItem
的映射配置,这种情况下可以同时翻译平台内和第三方的属性。翻译器在翻译数据时,需要绑定两个核心数据结构:
ConcurrentMap<String,JsonArray>
。ConcurrentMap<String, DictEpsilon>
。翻译器的初始化如下:
// 单边字典翻译器
final DictFabric fabric = DictFabric.create()
.dict(request.getDict()) // 绑定 ConcurrentMap<String,JsonArray> 字典
.epsilon(this.dict().getEpsilon()); // 绑定 ConcurrentMap<String,DictEpsilon> 定义
// 双边字典翻译器
final DictFabric fabric = DictFabric.create(mapping)
.dict(dictMap)
.epsilon(this.dict().getEpsilon());
单边翻译器 | 双边翻译器 | |
---|---|---|
inTo | 支持 | 支持 |
inFrom | 支持 | 支持 |
outTo | 不支持 | 支持 |
outFrom | 不支持 | 支持 |
字典的支持不会有副作用,也就是说,如果翻译失败,则直接不翻译传入的 JsonObject 或者 JsonArray,并不会在翻译失败的过程中报错,而且翻译出来的数据如果为 null 则会用 null 值填充,如果在 Epsilon 中的
in / out
定义反向的话,那么对应的翻译器的API也会反向,请开发人员注意方向问题。
如 Mapping 的定义如下:
{
"name": "z_name"
}
字典数据如:
{
"ci.name":[
{
"value": "uuid1",
"display": "display1"
},
{
"value": "uuid2",
"display": "display2"
}
]
}
字典消费定义限定为:
{
"name": {
"source": "ci.name",
"in": "display",
"out": "value"
}
}
设置数据:
数据 | 编号 | 场景 |
---|---|---|
name = uuid1 | S11 | Ox中存储的值为 uuid1 |
name = display1 | S12 | 从第三方传入的值为 display1 |
z_name = uuid1 | S21 | 拿到数据中为第三方字段 z_name |
z_name = display1 | S22 | 拿到的数据为第三方字段 z_name,存储的 display1 |
那么在上述流程中,看看调用不同的API的最终结果如:
调用API | 场景 | 翻译结果 |
---|---|---|
inTo | S11 | name = display1 |
inFrom | S11 | 不翻译 |
outTo | S11 | 不翻译 |
outFrom | S11 | 不翻译 |
inTo | S12 | 不翻译 |
inFrom | S12 | name = uuid1 |
outTo | S12 | 不翻译 |
outFrom | S12 | 不翻译 |
inTo | S21 | 不翻译 |
inFrom | S21 | 不翻译 |
outTo | S21 | z_name = display1 |
outFrom | S21 | 不翻译 |
inTo | S22 | 不翻译 |
inFrom | S22 | 不翻译 |
outTo | S22 | 不翻译 |
outFrom | S22 | z_name = uuid1 |
场景描述 | 方向 | 调用Api |
---|---|---|
Ox端 | value -> display | inTo |
Ox端 | display -> value | inFrom |
第三方 | value -> display | outTo |
第三方 | display -> value | outFrom |