diff --git a/README.md b/README.md index f6cbebe0def276c165e421452647c920f5cb7226..6ab610ce96ba59de90b31eee292f6af7bfb27b24 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## 介绍 -REC(Rule Engine Component)规则引擎组件:提供统一的规则处理方式和策略。 +REC(Rule Engine Component)规则引擎组件:提供统一的规则处理方式和策略。支持SDK接入、HTTP接入;只需要进行页面配置即可完成规则的处理,支持简单模式和复杂模式进行编辑。前后端分离项目,可独立部署,也可以前后端打包部署。 ## 分支迭代说明 @@ -21,6 +21,7 @@ REC(Rule Engine Component)规则引擎组件:提供统一的规则处理 - rec-engine:规则引擎处理器 - rec-engine-rule:规则引擎规则处理 - rec-engine-script:规则引擎脚本处理器 + - rec-engine-sdk:规则引擎SDK - rec-socket:rec通信管理 - rec-socket-client:rec通信客户端 - rec-socket-server:rec通信服务端 @@ -219,6 +220,7 @@ REC(Rule Engine Component)规则引擎组件:提供统一的规则处理 - 执行打包命令:mvn clean install - 主方法运行:AdminViewApplication - 浏览器访问:http://localhost:9999/#/login 登录即可 +- 前端如果报错,请禁用:ESLint ## TODO diff --git a/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/impl/BaseDataServiceImpl.java b/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/impl/BaseDataServiceImpl.java index 92b110d8330268cffe5850f87a92a17aa9aed81a..168794c445b866cbae45093ba92e3c6b9c206a00 100644 --- a/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/impl/BaseDataServiceImpl.java +++ b/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/impl/BaseDataServiceImpl.java @@ -59,7 +59,7 @@ public class BaseDataServiceImpl implements BaseDataService { eventDispatcher.fire(new LogEvent(insert.getUuid(), ModuleTypeEnum.REC_BASE_DATA, FastJsonUtils.toJSONString(insert), LogOperatorTypeEnum.CREATE)); } else { baseDataDAO.update(baseDataMapper.vo2do(baseData)); - eventDispatcher.fire(new LogEvent(baseData.getUuid(), ModuleTypeEnum.REC_BASE_DATA, FastJsonUtils.toJSONString(baseData), LogOperatorTypeEnum.CREATE)); + eventDispatcher.fire(new LogEvent(baseData.getUuid(), ModuleTypeEnum.REC_BASE_DATA, FastJsonUtils.toJSONString(baseData), LogOperatorTypeEnum.UPDATE)); } } diff --git a/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/impl/DataSourceServiceImpl.java b/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/impl/DataSourceServiceImpl.java index 0352182a4247809928d9d36bf3bdc1cbe3317615..f2abaf59feea057fbd729174501a3f2e51dc9c22 100644 --- a/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/impl/DataSourceServiceImpl.java +++ b/rec-admin/rec-admin-biz/src/main/java/cn/icanci/rec/admin/biz/service/impl/DataSourceServiceImpl.java @@ -1,15 +1,25 @@ package cn.icanci.rec.admin.biz.service.impl; +import cn.icanci.rec.admin.biz.event.log.LogEvent; import cn.icanci.rec.admin.biz.mapper.DataSourceMapper; import cn.icanci.rec.admin.biz.model.DataSourceDebugResult; import cn.icanci.rec.admin.biz.service.DataSourceService; import cn.icanci.rec.admin.dal.mongodb.common.PageList; import cn.icanci.rec.admin.dal.mongodb.daointerface.DataSourceDAO; import cn.icanci.rec.admin.dal.mongodb.dateobject.DataSourceDO; +import cn.icanci.rec.common.enums.DataSourceTypeEnum; +import cn.icanci.rec.common.enums.LogOperatorTypeEnum; +import cn.icanci.rec.common.enums.ModuleTypeEnum; import cn.icanci.rec.common.model.TextValue; import cn.icanci.rec.common.model.config.DataSourceVO; +import cn.icanci.rec.common.utils.FastJsonUtils; +import cn.icanci.rec.engine.script.RecScriptEngine; +import cn.icanci.rec.engine.script.context.RecScriptEngineContext; +import cn.icanci.rec.engine.script.wrapper.HttpResponseWrapper; +import cn.icanci.rec.spi.event.EventDispatcher; import java.util.List; +import java.util.concurrent.*; import javax.annotation.Resource; @@ -28,6 +38,10 @@ public class DataSourceServiceImpl implements DataSourceService { private DataSourceDAO dataSourceDAO; @Resource private DataSourceMapper dataSourceMapper; + @Resource + private RecScriptEngine recScriptEngine; + @Resource + private EventDispatcher eventDispatcher; @Override public List queryAll() { @@ -37,9 +51,12 @@ public class DataSourceServiceImpl implements DataSourceService { @Override public void save(DataSourceVO dataSource) { if (doInsert(dataSource)) { - dataSourceDAO.insert(dataSourceMapper.vo2do(dataSource)); + DataSourceDO insert = dataSourceMapper.vo2do(dataSource); + dataSourceDAO.insert(insert); + eventDispatcher.fire(new LogEvent(insert.getUuid(), ModuleTypeEnum.REC_DATA_SOURCE, FastJsonUtils.toJSONString(insert), LogOperatorTypeEnum.CREATE)); } else { dataSourceDAO.update(dataSourceMapper.vo2do(dataSource)); + eventDispatcher.fire(new LogEvent(dataSource.getUuid(), ModuleTypeEnum.REC_DATA_SOURCE, FastJsonUtils.toJSONString(dataSource), LogOperatorTypeEnum.UPDATE)); } } @@ -81,7 +98,80 @@ public class DataSourceServiceImpl implements DataSourceService { @Override public DataSourceDebugResult debug(DataSourceVO dataSource) { - // TODO http 请求放哪里 - return null; + DataSourceDebugResult result = new DataSourceDebugResult(); + result.setDataSourceType(dataSource.getDataSourceType().getDesc()); + + try { + DataSourceTypeEnum dataSourceType = dataSource.getDataSourceType(); + switch (dataSourceType) { + case SCRIPT: + DataSourceVO.ScriptInfo scriptInfo = dataSource.getScriptInfo(); + result.setScriptType(scriptInfo.getScriptType().getDesc()); + // 脚本执行 + RecScriptEngineContext context = scriptExecutor(scriptInfo); + if (context.isSuccess()) { + result.setSuccess(true); + result.setRealResult(context.getRealRetVal()); + } else { + result.setSuccess(false); + result.setExceptionMessage(context.getThrowable().getMessage()); + } + return result; + case HTTP: + DataSourceVO.HttpInfo httpInfo = dataSource.getHttpInfo(); + HttpResponseWrapper wrapper = recScriptEngine.httpEval(httpInfo.getHttpRequestType(), httpInfo.getReqUrl(), httpInfo.getReqParam(), httpInfo.getTimeout()); + if (wrapper.isSuccess()) { + result.setSuccess(true); + result.setRealResult(wrapper.getResponse()); + } else { + result.setSuccess(false); + result.setExceptionMessage(wrapper.getException().getMessage()); + } + return result; + default: + // no op + } + + return result; + } catch (Throwable e) { + result.setSuccess(false); + result.setExceptionMessage(e.getMessage()); + return result; + } + } + + /** + * 脚本执行处理 + * + * @param scriptInfo 执行脚本相关信息 + * @throws InterruptedException + * @throws ExecutionException + * @throws TimeoutException + * @return RecScriptEngineContext + */ + private RecScriptEngineContext scriptExecutor(DataSourceVO.ScriptInfo scriptInfo) throws InterruptedException, ExecutionException, TimeoutException { + FutureTask> task = new FutureTask<>(new ScriptExecutor(scriptInfo, recScriptEngine)); + // TODO 启动计算:测试使用单独线程、运行时应创建线程池 + new Thread(task).start(); + // 等待执行结果 + return task.get(scriptInfo.getTimeout(), TimeUnit.SECONDS); + } + + /** 执行器 */ + private static class ScriptExecutor implements Callable> { + /** scriptInfo */ + private final DataSourceVO.ScriptInfo scriptInfo; + /** recScriptEngine执行引擎 */ + private final RecScriptEngine recScriptEngine; + + public ScriptExecutor(DataSourceVO.ScriptInfo scriptInfo, RecScriptEngine recScriptEngine) { + this.scriptInfo = scriptInfo; + this.recScriptEngine = recScriptEngine; + } + + @Override + public RecScriptEngineContext call() throws Exception { + return recScriptEngine.eval(scriptInfo.getScriptType(), scriptInfo.getScriptContent()); + } } } diff --git a/rec-admin/rec-admin-views/src/main/resources/vueboot/src/views/ruleConfig/dataSource.vue b/rec-admin/rec-admin-views/src/main/resources/vueboot/src/views/ruleConfig/dataSource.vue new file mode 100644 index 0000000000000000000000000000000000000000..25600974af91ac7537f2daeeef3870cb14c020df --- /dev/null +++ b/rec-admin/rec-admin-views/src/main/resources/vueboot/src/views/ruleConfig/dataSource.vue @@ -0,0 +1,164 @@ + + diff --git a/rec-admin/rec-admin-views/src/main/resources/vueboot/src/views/ruleConfig/dialog/dataSourceForm.vue b/rec-admin/rec-admin-views/src/main/resources/vueboot/src/views/ruleConfig/dialog/dataSourceForm.vue new file mode 100644 index 0000000000000000000000000000000000000000..550df7956d36fca334f08f0f27f589205616a7f8 --- /dev/null +++ b/rec-admin/rec-admin-views/src/main/resources/vueboot/src/views/ruleConfig/dialog/dataSourceForm.vue @@ -0,0 +1,152 @@ + + + diff --git a/rec-common/src/main/java/cn/icanci/rec/common/aggregation/RuleAggregation.java b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/RuleAggregation.java new file mode 100644 index 0000000000000000000000000000000000000000..339eca3bafa934a37463e76e2b8494910cadc371 --- /dev/null +++ b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/RuleAggregation.java @@ -0,0 +1,98 @@ +package cn.icanci.rec.common.aggregation; + +import cn.icanci.rec.common.aggregation.model.*; + +import java.util.List; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * 规则聚合-单个规则需要的配置数据信息 + * + * @author icanci + * @since 1.0 Created in 2022/11/15 15:44 + */ +public class RuleAggregation { + /** 域 */ + private DomainDTO domain; + /** 场景 */ + private SceneDTO.ScenePair scenePair; + /** 基础数据 */ + private List baseDatas; + /** 元数据 */ + private List metadatas; + /** 数据源 */ + private DataSourceDTO dataSource; + /** 策略 */ + private StrategyDTO strategy; + + public DomainDTO getDomain() { + return domain; + } + + public void setDomain(DomainDTO domain) { + this.domain = domain; + } + + public SceneDTO.ScenePair getScenePair() { + return scenePair; + } + + public void setScenePair(SceneDTO.ScenePair scenePair) { + this.scenePair = scenePair; + } + + public List getBaseDatas() { + return baseDatas; + } + + public void setBaseDatas(List baseDatas) { + this.baseDatas = baseDatas; + } + + public List getMetadatas() { + return metadatas; + } + + public void setMetadatas(List metadatas) { + this.metadatas = metadatas; + } + + public DataSourceDTO getDataSource() { + return dataSource; + } + + public void setDataSource(DataSourceDTO dataSource) { + this.dataSource = dataSource; + } + + public StrategyDTO getStrategy() { + return strategy; + } + + public void setStrategy(StrategyDTO strategy) { + this.strategy = strategy; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + RuleAggregation that = (RuleAggregation) o; + return Objects.equals(domain, that.domain) && Objects.equals(scenePair, that.scenePair) && Objects.equals(baseDatas, that.baseDatas) + && Objects.equals(metadatas, that.metadatas) && Objects.equals(dataSource, that.dataSource) && Objects.equals(strategy, that.strategy); + } + + @Override + public int hashCode() { + return Objects.hash(domain, scenePair, baseDatas, metadatas, dataSource, strategy); + } + + @Override + public String toString() { + return new StringJoiner(",").add("domain=" + domain).add("scenePair=" + scenePair).add("baseDatas=" + baseDatas).add("metadatas=" + metadatas) + .add("dataSource=" + dataSource).add("strategy=" + strategy).toString(); + } +} diff --git a/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/BaseDTO.java b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/BaseDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..49c242faf5d7594f6ccbe7faa3aa3a4354e92114 --- /dev/null +++ b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/BaseDTO.java @@ -0,0 +1,103 @@ +package cn.icanci.rec.common.aggregation.model; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/15 17:12 + */ +public class BaseDTO implements Serializable { + private static final long serialVersionUID = 1031085394922945504L; + + /** + * 文档id + */ + private String id; + + /** + * 雪花算法随机UUID + */ + private String uuid; + + /** + * 功能描述 + */ + private String desc; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 状态 0有效,1无效 + */ + private int isDelete; + + /** + * 环境 + */ + private String env; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public int getIsDelete() { + return isDelete; + } + + public void setIsDelete(int isDelete) { + this.isDelete = isDelete; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } +} diff --git a/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/BaseDataDO.java b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/BaseDataDO.java new file mode 100644 index 0000000000000000000000000000000000000000..0abb2281f829793c54475108d440e18ec7924d40 --- /dev/null +++ b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/BaseDataDO.java @@ -0,0 +1,107 @@ +package cn.icanci.rec.common.aggregation.model; + +import cn.icanci.rec.common.enums.DataTypeEnum; +import cn.icanci.rec.common.enums.ResultTypeEnum; +import cn.icanci.rec.common.enums.ScriptTypeEnum; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/15 17:14 + */ +public class BaseDataDO extends BaseDTO { + private static final long serialVersionUID = -509622609203854310L; + /** + * 域Code + */ + private String domainCode; + /** + * 基础数据名称 + */ + private String fieldName; + /** + * 数据类型(布尔、字符串、数值、日期、元数据等) + * + * @see DataTypeEnum#name() + */ + private String dataType; + /** + * 关联的元数据uuid + * + * {@link DataTypeEnum#METADATA} + */ + private String metadataUuid; + /** + * 脚本执行类型 + * + * @see ScriptTypeEnum#name() + */ + private String scriptType; + /** + * 脚本内容 + */ + private String scriptContent; + /** + * TODO 是否有必要 + * 脚本执行返回类型(只能是基本数据类型) + * + * @see ResultTypeEnum#name() + */ + @Deprecated + private String resultType; + + public String getDomainCode() { + return domainCode; + } + + public void setDomainCode(String domainCode) { + this.domainCode = domainCode; + } + + public String getFieldName() { + return fieldName; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + public String getDataType() { + return dataType; + } + + public void setDataType(String dataType) { + this.dataType = dataType; + } + + public String getMetadataUuid() { + return metadataUuid; + } + + public void setMetadataUuid(String metadataUuid) { + this.metadataUuid = metadataUuid; + } + + public String getScriptType() { + return scriptType; + } + + public void setScriptType(String scriptType) { + this.scriptType = scriptType; + } + + public String getScriptContent() { + return scriptContent; + } + + public void setScriptContent(String scriptContent) { + this.scriptContent = scriptContent; + } + + public String getResultType() { + return resultType; + } + + public void setResultType(String resultType) { + this.resultType = resultType; + } +} diff --git a/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/DataSourceDTO.java b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/DataSourceDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..9ede3d6560b95f20d62a2ee8f91edb3b4c8a66ef --- /dev/null +++ b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/DataSourceDTO.java @@ -0,0 +1,216 @@ +package cn.icanci.rec.common.aggregation.model; + +import cn.icanci.rec.common.enums.DataSourceTypeEnum; +import cn.icanci.rec.common.enums.HttpRequestTypeEnum; +import cn.icanci.rec.common.enums.ScriptTypeEnum; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/15 17:15 + */ +public class DataSourceDTO extends BaseDTO { + private static final long serialVersionUID = -236906855236316919L; + + /** + * 数据源名称 + */ + private String dataSourceName; + /** + * 数据源类型 + * @see DataSourceTypeEnum @name() + */ + private String dataSourceType; + /** + * 数据源为脚本的执行数据集 + */ + private ScriptInfo scriptInfo; + /** + * 数据源为HTTP的执行数据集 + */ + private HttpInfo httpInfo; + /** + * 数据源为SQL的执行数据集 + */ + private SqlInfo sqlInfo; + + /** + * 数据源为脚本的执行数据集 + */ + public static class ScriptInfo { + /** + * 脚本执行类型 + * + * @see ScriptTypeEnum#name() + * + */ + private String scriptType; + /** + * 脚本内容 + */ + private String scriptContent; + + /** + * 执行超时时间,秒 + * 为0则不做限制 + */ + private int timeout; + + public String getScriptType() { + return scriptType; + } + + public void setScriptType(String scriptType) { + this.scriptType = scriptType; + } + + public String getScriptContent() { + return scriptContent; + } + + public void setScriptContent(String scriptContent) { + this.scriptContent = scriptContent; + } + + public int getTimeout() { + return timeout; + } + + public void setTimeout(int timeout) { + this.timeout = timeout; + } + } + + /** + * 数据源为HTTP的执行数据集 + */ + public static class HttpInfo { + /** + * 请求数据类型 + * + * @see HttpRequestTypeEnum#name() + */ + private String httpRequestType; + /** + * 请求接口 + */ + private String reqUrl; + /** + * 请求参数 + * + * @see HttpRequestTypeEnum#POST 时有效 + */ + private String reqParam; + + /** + * 请求超时时间,秒 + * 为0则不做限制,则最大超时时间为5s + */ + private int timeout; + + public String getHttpRequestType() { + return httpRequestType; + } + + public void setHttpRequestType(String httpRequestType) { + this.httpRequestType = httpRequestType; + } + + public String getReqUrl() { + return reqUrl; + } + + public void setReqUrl(String reqUrl) { + this.reqUrl = reqUrl; + } + + public String getReqParam() { + return reqParam; + } + + public void setReqParam(String reqParam) { + this.reqParam = reqParam; + } + + public int getTimeout() { + return timeout; + } + + public void setTimeout(int timeout) { + this.timeout = timeout; + } + } + + /** + * 数据源为SQL的执行数据集 + */ + public static class SqlInfo { + /** + * SQL 语句,只支持查询语句 + * + * 查询默认数据库 rec_ext + */ + private String sql; + + /** + * 执行超时时间,秒 + * 为0则不作限制 + */ + private int timeout; + + public String getSql() { + return sql; + } + + public void setSql(String sql) { + this.sql = sql; + } + + public int getTimeout() { + return timeout; + } + + public void setTimeout(int timeout) { + this.timeout = timeout; + } + } + + public String getDataSourceName() { + return dataSourceName; + } + + public void setDataSourceName(String dataSourceName) { + this.dataSourceName = dataSourceName; + } + + public String getDataSourceType() { + return dataSourceType; + } + + public void setDataSourceType(String dataSourceType) { + this.dataSourceType = dataSourceType; + } + + public ScriptInfo getScriptInfo() { + return scriptInfo; + } + + public void setScriptInfo(ScriptInfo scriptInfo) { + this.scriptInfo = scriptInfo; + } + + public HttpInfo getHttpInfo() { + return httpInfo; + } + + public void setHttpInfo(HttpInfo httpInfo) { + this.httpInfo = httpInfo; + } + + public SqlInfo getSqlInfo() { + return sqlInfo; + } + + public void setSqlInfo(SqlInfo sqlInfo) { + this.sqlInfo = sqlInfo; + } +} diff --git a/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/DomainDTO.java b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/DomainDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..8aee435cca2e51ce45b9ff301e3a20112cecfac0 --- /dev/null +++ b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/DomainDTO.java @@ -0,0 +1,36 @@ +package cn.icanci.rec.common.aggregation.model; + +/** + * 域网络传输模型 + * + * @author icanci + * @since 1.0 Created in 2022/11/15 15:44 + */ +public class DomainDTO extends BaseDTO { + private static final long serialVersionUID = -7107977844423682947L; + + /** + * 域名称 + */ + private String domainName; + /** + * 域Code + */ + private String domainCode; + + public String getDomainName() { + return domainName; + } + + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + public String getDomainCode() { + return domainCode; + } + + public void setDomainCode(String domainCode) { + this.domainCode = domainCode; + } +} diff --git a/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/MetadataDTO.java b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/MetadataDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..24f5b02507d9cb445e5e1b832f8b0de0758d60d1 --- /dev/null +++ b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/MetadataDTO.java @@ -0,0 +1,77 @@ +package cn.icanci.rec.common.aggregation.model; + +import java.util.List; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/15 17:15 + */ +public class MetadataDTO extends BaseDTO { + private static final long serialVersionUID = -5862980841899784907L; + /** + * 域Code + */ + private String domainCode; + /** + * 元数据名称 + */ + private String metadataName; + /** + * 元数据对 + */ + private List metadataPairs; + + public String getDomainCode() { + return domainCode; + } + + public void setDomainCode(String domainCode) { + this.domainCode = domainCode; + } + + public String getMetadataName() { + return metadataName; + } + + public void setMetadataName(String metadataName) { + this.metadataName = metadataName; + } + + public List getMetadataPairs() { + return metadataPairs; + } + + public void setMetadataPairs(List metadataPairs) { + this.metadataPairs = metadataPairs; + } + + /** + * 元数据对 + */ + public static class MetadataPair { + /** + * key + */ + private String key; + /** + * value + */ + private String value; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } +} diff --git a/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/SceneDTO.java b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/SceneDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..f6378517d9f4ab4657b94928c7820352086cffb7 --- /dev/null +++ b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/SceneDTO.java @@ -0,0 +1,66 @@ +package cn.icanci.rec.common.aggregation.model; + +import java.util.List; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/15 17:16 + */ +public class SceneDTO extends BaseDTO { + private static final long serialVersionUID = 6236086133690446406L; + + /** + * 域Code + */ + private String domainCode; + /** + * 场景对 + */ + private List scenePairs; + + public String getDomainCode() { + return domainCode; + } + + public void setDomainCode(String domainCode) { + this.domainCode = domainCode; + } + + public List getScenePairs() { + return scenePairs; + } + + public void setScenePairs(List scenePairs) { + this.scenePairs = scenePairs; + } + + /** + * 场景对 + */ + public static class ScenePair { + /** + * 场景名称 + */ + private String sceneName; + /** + * 场景Code + */ + private String sceneCode; + + public String getSceneName() { + return sceneName; + } + + public void setSceneName(String sceneName) { + this.sceneName = sceneName; + } + + public String getSceneCode() { + return sceneCode; + } + + public void setSceneCode(String sceneCode) { + this.sceneCode = sceneCode; + } + } +} diff --git a/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/StrategyDTO.java b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/StrategyDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..aa20ca21609e1d43fb379d6bc0d3f0e2c3e11c7f --- /dev/null +++ b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/model/StrategyDTO.java @@ -0,0 +1,287 @@ +package cn.icanci.rec.common.aggregation.model; + +import cn.icanci.rec.common.enums.*; + +import java.util.List; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/15 17:17 + */ +public class StrategyDTO extends BaseDTO { + private static final long serialVersionUID = 9136167863490238394L; + + /** + * 域Code + */ + private String domainCode; + /** + * 场景Code + */ + private String sceneCode; + /** + * 策略组名称 + */ + private String strategyName; + /** + * 数据源类型(脚本、接口、SQL) + * + * @see DataSourceTypeEnum#name() + */ + private String dataSourceType; + /** + * 数据源关联uuid + */ + private String dataSourceUuid; + /** + * 规则配置类型(默认为List) + * + * @see RuleTypeEnum#name() + */ + private String ruleType; + /** + * 规则配置类型为List时候的规则数据 + */ + private RuleListInfo ruleListInfo; + /** + * 规则配置类型为Tree时候的规则数据 + */ + private RuleTreeInfo ruleTreeInfo; + + public String getDomainCode() { + return domainCode; + } + + public void setDomainCode(String domainCode) { + this.domainCode = domainCode; + } + + public String getSceneCode() { + return sceneCode; + } + + public void setSceneCode(String sceneCode) { + this.sceneCode = sceneCode; + } + + public String getStrategyName() { + return strategyName; + } + + public void setStrategyName(String strategyName) { + this.strategyName = strategyName; + } + + public String getDataSourceType() { + return dataSourceType; + } + + public void setDataSourceType(String dataSourceType) { + this.dataSourceType = dataSourceType; + } + + public String getDataSourceUuid() { + return dataSourceUuid; + } + + public void setDataSourceUuid(String dataSourceUuid) { + this.dataSourceUuid = dataSourceUuid; + } + + public String getRuleType() { + return ruleType; + } + + public void setRuleType(String ruleType) { + this.ruleType = ruleType; + } + + public RuleListInfo getRuleListInfo() { + return ruleListInfo; + } + + public void setRuleListInfo(RuleListInfo ruleListInfo) { + this.ruleListInfo = ruleListInfo; + } + + public RuleTreeInfo getRuleTreeInfo() { + return ruleTreeInfo; + } + + public void setRuleTreeInfo(RuleTreeInfo ruleTreeInfo) { + this.ruleTreeInfo = ruleTreeInfo; + } + + /** + * 规则配置类型为List时候的规则数据 + */ + public static class RuleListInfo { + /** + * 平级结构 + * + * 多个conditions为或的关系 + */ + private List conditions; + + public List getConditions() { + return conditions; + } + + public void setConditions(List conditions) { + this.conditions = conditions; + } + } + + /** + * 平级结构 + */ + public static class Condition { + /** + * 组集合 + * 每一组内为且的关系 + */ + private List group; + + public List getGroup() { + return group; + } + + public void setGroup(List group) { + this.group = group; + } + } + + /** + * 单元结构 + */ + public static class SingleCondition { + + /** 单元名称 */ + private String name; + + /** 左值:基础数据uuid */ + private String leftValue; + + /** + * 操作符 + * + * @see OperatorEnum#name() + */ + private String operator; + + /** 右值 */ + private String rightValue; + + /** + * 是否中断执行 + * + * @see InterruptEnum#name() + */ + private String interrupt; + + /** + * 命中到当前条件的返回值类型 + * + * 满足 {@link InterruptEnum#TRUE } 时候返回值 + * @see ResultTypeEnum#name() + */ + private String resultType; + /** + * 命中到当前条件的返回值 + * + * 满足 {@link InterruptEnum#TRUE } 时候返回值 + */ + private String returnVal; + + /** + * 当前规则的子配置项 + * 一个规则自配置可以有多组,每组可能有多个,每组的每个也是一个配置项 + * + * Tree 结构的 SingleCondition#children 会存储值 + * 非Tree结构则为空数组 + */ + List children; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLeftValue() { + return leftValue; + } + + public void setLeftValue(String leftValue) { + this.leftValue = leftValue; + } + + public String getOperator() { + return operator; + } + + public void setOperator(String operator) { + this.operator = operator; + } + + public String getRightValue() { + return rightValue; + } + + public void setRightValue(String rightValue) { + this.rightValue = rightValue; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public String getInterrupt() { + return interrupt; + } + + public void setInterrupt(String interrupt) { + this.interrupt = interrupt; + } + + public String getResultType() { + return resultType; + } + + public void setResultType(String resultType) { + this.resultType = resultType; + } + + public String getReturnVal() { + return returnVal; + } + + public void setReturnVal(String returnVal) { + this.returnVal = returnVal; + } + } + + /** + * 规则配置类型为Tree时候的规则数据 + */ + public static class RuleTreeInfo { + /** + * 多个conditions为或的关系 + */ + private List conditions; + + public List getConditions() { + return conditions; + } + + public void setConditions(List conditions) { + this.conditions = conditions; + } + } +} diff --git a/rec-common/src/main/java/cn/icanci/rec/common/aggregation/package-info.java b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..61ab2148fe4b8efc8fe38389249be5505195af5a --- /dev/null +++ b/rec-common/src/main/java/cn/icanci/rec/common/aggregation/package-info.java @@ -0,0 +1,7 @@ +/** + * 推送聚合模型 + * + * @author icanci + * @since 1.0 Created in 2022/11/15 15:37 + */ +package cn.icanci.rec.common.aggregation; \ No newline at end of file diff --git a/rec-common/src/main/java/cn/icanci/rec/common/enums/ModuleTypeEnum.java b/rec-common/src/main/java/cn/icanci/rec/common/enums/ModuleTypeEnum.java index d0e053204dadbe3f883ec6b7170bad2e71ed0c3d..6319ff29b35a882e3483f8b1b31b0200f8156f37 100644 --- a/rec-common/src/main/java/cn/icanci/rec/common/enums/ModuleTypeEnum.java +++ b/rec-common/src/main/java/cn/icanci/rec/common/enums/ModuleTypeEnum.java @@ -20,6 +20,10 @@ public enum ModuleTypeEnum { * REC_BASE_DATA */ REC_BASE_DATA("REC_BASE_DATA", "规则基础数据"), + /** + * REC_DATA_SOURCE + */ + REC_DATA_SOURCE("REC_DATA_SOURCE", "规则数据源"), ; diff --git a/rec-core/src/main/resources/application.yml b/rec-core/src/main/resources/application.yml index 36350a81de64134070e73a77e783b785e17d2b84..bae25d0497319f35b51fd4d4a46c130a475c7355 100644 --- a/rec-core/src/main/resources/application.yml +++ b/rec-core/src/main/resources/application.yml @@ -9,8 +9,11 @@ server: logging: config: classpath:log4j2.xml +# 接入方需要上报自己的信息给注册中心 rec: env: test + project-union-key: + project-union-name: spring: # datasource: diff --git a/rec-engine/rec-engine-rule/src/main/java/cn/icanci/rec/engine/rule/RuleAggregationCluster.java b/rec-engine/rec-engine-rule/src/main/java/cn/icanci/rec/engine/rule/RuleAggregationCluster.java new file mode 100644 index 0000000000000000000000000000000000000000..afb1787b1172764de0ac44c60b739ca69f416a8f --- /dev/null +++ b/rec-engine/rec-engine-rule/src/main/java/cn/icanci/rec/engine/rule/RuleAggregationCluster.java @@ -0,0 +1,12 @@ +package cn.icanci.rec.engine.rule; + +/** + * 规则聚合簇 + * + * @author icanci + * @since 1.0 Created in 2022/11/15 15:32 + */ +public interface RuleAggregationCluster { + + void build(); +} diff --git a/rec-engine/rec-engine-rule/src/main/java/cn/icanci/rec/engine/rule/impl/RuleAggregationClusterImpl.java b/rec-engine/rec-engine-rule/src/main/java/cn/icanci/rec/engine/rule/impl/RuleAggregationClusterImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..a4ae3846296ff9818961bc4aca4f911ae26d4ccc --- /dev/null +++ b/rec-engine/rec-engine-rule/src/main/java/cn/icanci/rec/engine/rule/impl/RuleAggregationClusterImpl.java @@ -0,0 +1,14 @@ +package cn.icanci.rec.engine.rule.impl; + +import cn.icanci.rec.engine.rule.RuleAggregationCluster; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/15 15:36 + */ +public class RuleAggregationClusterImpl implements RuleAggregationCluster { + @Override + public void build() { + + } +} diff --git a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/context/RecScriptEngineContext.java b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/context/RecScriptEngineContext.java index 4c88aefeac247fd8f373a0af2d0bc09e7584aff1..ee477eaf390952de2e54e776d3d6f6e0798a483f 100644 --- a/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/context/RecScriptEngineContext.java +++ b/rec-engine/rec-engine-script/src/main/java/cn/icanci/rec/engine/script/context/RecScriptEngineContext.java @@ -61,6 +61,15 @@ public class RecScriptEngineContext implements Serializable { // ============================ ability method ============================ + /** + * 是否执行成功 + * + * @return 返回是否执行成功 + */ + public boolean isSuccess() { + return retVal != null && throwable == null; + } + /** * 获取真正的执行结果,并且对返回结果进行校验 * @@ -84,6 +93,8 @@ public class RecScriptEngineContext implements Serializable { if (type == String.class) { return (T) String.valueOf(retVal); } + // 非标准类型返回对象,此类归属脚本执行结果返回 + return retVal; } catch (Throwable e) { if (this.throwable != null) { this.throwable.addSuppressed(e); diff --git a/rec-engine/rec-engine-script/src/test/java/cn/icanci/rec/engine/script/test/RecScriptEngineManagerTest.java b/rec-engine/rec-engine-script/src/test/java/cn/icanci/rec/engine/script/test/RecScriptEngineManagerTest.java index bc303ce337239172e03e58415b10abec889ef36d..eb8f6e9b1e3d7875c6a8271d3fc79c780d0f8212 100644 --- a/rec-engine/rec-engine-script/src/test/java/cn/icanci/rec/engine/script/test/RecScriptEngineManagerTest.java +++ b/rec-engine/rec-engine-script/src/test/java/cn/icanci/rec/engine/script/test/RecScriptEngineManagerTest.java @@ -20,9 +20,9 @@ public class RecScriptEngineManagerTest { @Test public void testRecScriptEngineManager() { RecScriptEngine recScriptEngine = RecScriptEngineManager.getRecScriptEngine(); - RecScriptEngineContext context = recScriptEngine.eval(ScriptTypeEnum.MVEL2, "1+2", Integer.class); + RecScriptEngineContext context = recScriptEngine.eval(ScriptTypeEnum.MVEL2, "1+2", Object.class); System.out.println(context); - Integer retVal = context.getRealRetVal(); + Object retVal = context.getRealRetVal(); System.out.println(retVal); System.out.println(context); } @@ -46,10 +46,10 @@ public class RecScriptEngineManagerTest { @Test public void fastjsonIsJson() { -// System.out.println(FastJsonUtils.isJson("「9999")); + // System.out.println(FastJsonUtils.isJson("「9999")); System.out.println(FastJsonUtils.isJson("TRUE")); System.out.println(FastJsonUtils.isJson("false ")); -// System.out.println(FastJsonUtils.isJson("11.1")); + // System.out.println(FastJsonUtils.isJson("11.1")); System.out.println(Boolean.parseBoolean("true")); System.out.println(Boolean.parseBoolean("false")); }