Compare commits

..

2 Commits

Author SHA1 Message Date
gaibu bc86356078 enhancement #I9FM3I chain 中增加一个指纹值 2024-05-17 22:50:32 +08:00
gaibu 33197922d6 enhancement #I9FM3I chain 中增加一个指纹值 2024-05-17 22:43:09 +08:00
42 changed files with 467 additions and 659 deletions

View File

@ -11,7 +11,7 @@
## Overview ## Overview
LiteFlow is a lightweight and powerful rules engine framework, which can be used in the field of complex componenzed business orchestration. DSL rules drive the whole complex business, and can achieve smooth refresh hot deployment, supporting the embedding of multiple scripting language rules. Help the system become more silky and flexible. LiteFlow is a lightweight and powerful rules engine framework, which can be used in the field of complex componenzed business orchestration. DSL rules drive the whole complex business, and can achieve smooth refresh hot deployment, supporting the embedding of multiple scripting language rules. Help the system become more silky and flexible.
LiteFlow was officially open-sourced in 2020 and has since become an indispensable presence in the field of open-source rule engines in China. What's more, the most crucial aspect is that LiteFlow is an open-source project that continues to iterate at a high speed. LiteFlow was officially open source in 2020 and won the title of "the Most Popular Open Source software" in China in 2021. Gitee-GVP award in 2022. It is an open source project that is growing rapidly.
LiteFlow is a community-driven project. We take community building very seriously. We have a community of more than 4000 users who can respond to any problems or suggestions they encounter. LiteFlow is a community-driven project. We take community building very seriously. We have a community of more than 4000 users who can respond to any problems or suggestions they encounter.
@ -31,7 +31,7 @@ You can find out how to join the community on the official website!
* **Wide support:** LiteFlow works regardless of whether your project is built on Springboot, Spring, or any other Java framework. * **Wide support:** LiteFlow works regardless of whether your project is built on Springboot, Spring, or any other Java framework.
* **JDK support:** From JDK8 to JDK17. Don't worry about JDK versions. * **JDK support:** From JDK8 to JDK17. Don't worry about JDK versions.
* **Full Springboot support:** Supports Springboot 2.X through the latest Springboot 3.X. * **Full Springboot support:** Supports Springboot 2.X through the latest Springboot 3.X.
* **Scripting language support:** You can define script language nodes that support Groovy, Javascript, QLExpress, Python, Lua, Kotlin and Aviator. More script languages will be supported in the future. * **Scripting language support:** You can define script language nodes that support Groovy, Javascript, QLExpress, Python, Lua, and Aviator. More script languages will be supported in the future.
* **Rule nesting support:** You can use simple expressions to create multiple nested complex logic layouts if you want. * **Rule nesting support:** You can use simple expressions to create multiple nested complex logic layouts if you want.
* **Component retry support:** Components can support retry, and each component can customize the retry configuration and specify exceptions. * **Component retry support:** Components can support retry, and each component can customize the retry configuration and specify exceptions.
* **Context isolation mechanism:** Reliable context isolation mechanism, you do not have to worry about high concurrency data flow. * **Context isolation mechanism:** Reliable context isolation mechanism, you do not have to worry about high concurrency data flow.

View File

@ -9,9 +9,9 @@
## 🌈概述 ## 🌈概述
LiteFlow是一个轻量且强大的国产规则引擎框架可用于复杂的组件化业务的编排领域独有的DSL规则驱动整个复杂业务并可实现平滑刷新热部署支持多种脚本语言规则的嵌入。帮助系统变得更加丝滑且灵活。 LiteFlow是一个轻量且强大的国产规则引擎框架可用于复杂的组件化业务的编排领域独有的DSL规则驱动整个复杂业务并可实现平滑刷新热部署支持多种脚本语言规则的嵌入。帮助系统变得更加丝滑且灵活。
LiteFlow于2020年正式开源直到现在已经是国内开源规则引擎中不可忽视的存在而且最关键的是LiteFlow还是一个持续高速迭代的开源项目。 LiteFlow于2020年正式开源2021年获得开源中国年度最受欢迎开源软件殊荣。于2022年获得Gitee最有价值开源项目(GVP)荣誉。是一个正处在高速发展中的开源项目。
LiteFlow是一个由社区驱动的项目我们非常重视社区建设拥有一个5000多人的使用者社区在使用中碰到任何问题或者建议都可以在社区中反应。 LiteFlow是一个由社区驱动的项目我们非常重视社区建设拥有一个4000多人的使用者社区在使用中碰到任何问题或者建议都可以在社区中反应。
你在官网中可以找到加入社区的方式! 你在官网中可以找到加入社区的方式!
@ -29,7 +29,7 @@ LiteFlow是一个由社区驱动的项目我们非常重视社区建设
* **支持广泛:** 不管你的项目是不是基于SpringbootSpring还是任何其他java框架构建LiteFlow都能游刃有余。 * **支持广泛:** 不管你的项目是不是基于SpringbootSpring还是任何其他java框架构建LiteFlow都能游刃有余。
* **JDK支持** 从JDK8到JDK17全部支持。无需担心JDK版本。 * **JDK支持** 从JDK8到JDK17全部支持。无需担心JDK版本。
* **Springboot支持全面** 支持Springboot 2.X到最新的Springboot 3.X。 * **Springboot支持全面** 支持Springboot 2.X到最新的Springboot 3.X。
* **脚本语言支持:** 可以定义脚本语言节点支持GroovyJavascriptQLExpressPythonLuaAviatorJavaKotlin。未来还会支持更多的脚本语言。 * **脚本语言支持:** 可以定义脚本语言节点支持GroovyJavascriptQLExpressPythonLuaAviatorJava。未来还会支持更多的脚本语言。
* **脚本和Java全打通** 所有脚本语言均可调用Java方法甚至于可以引用任意的实例在脚本中调用RPC也是支持的。 * **脚本和Java全打通** 所有脚本语言均可调用Java方法甚至于可以引用任意的实例在脚本中调用RPC也是支持的。
* **规则嵌套支持:** 只要你想的出,你可以利用简单的表达式完成多重嵌套的复杂逻辑编排。 * **规则嵌套支持:** 只要你想的出,你可以利用简单的表达式完成多重嵌套的复杂逻辑编排。
* **组件重试支持:** 组件可以支持重试,每个组件均可自定义重试配置和指定异常。 * **组件重试支持:** 组件可以支持重试,每个组件均可自定义重试配置和指定异常。

View File

@ -136,7 +136,8 @@ public class LiteFlowChainELBuilder {
public LiteFlowChainELBuilder setRoute(String routeEl){ public LiteFlowChainELBuilder setRoute(String routeEl){
if (StrUtil.isBlank(routeEl)) { if (StrUtil.isBlank(routeEl)) {
return this; String errMsg = StrUtil.format("You have defined the label <route> but there is no el in the chain route[{}].", chain.getChainId());
throw new FlowSystemException(errMsg);
} }
List<String> errorList = new ArrayList<>(); List<String> errorList = new ArrayList<>();
try { try {
@ -182,6 +183,15 @@ public class LiteFlowChainELBuilder {
} }
this.chain.setEl(elStr); this.chain.setEl(elStr);
// 判断是否已经包含了这个EL
if (this.chain.isExist()) {
if (LOG.isDebugEnabled()) {
LOG.debug("chain[{}] el[{}] is already contains, skip", chain.getChainId(), elStr);
}
return this;
}
LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
// 如果设置了不检查Node是否存在那么这里是不解析的 // 如果设置了不检查Node是否存在那么这里是不解析的
if (liteflowConfig.getParseMode().equals(ParseModeEnum.PARSE_ONE_ON_FIRST_EXEC)){ if (liteflowConfig.getParseMode().equals(ParseModeEnum.PARSE_ONE_ON_FIRST_EXEC)){
@ -233,9 +243,6 @@ public class LiteFlowChainELBuilder {
} }
public LiteFlowChainELBuilder setNamespace(String nameSpace){ public LiteFlowChainELBuilder setNamespace(String nameSpace){
if (StrUtil.isBlank(nameSpace)) {
nameSpace = ChainConstant.DEFAULT_NAMESPACE;
}
this.chain.setNamespace(nameSpace); this.chain.setNamespace(nameSpace);
return this; return this;
} }
@ -258,6 +265,17 @@ public class LiteFlowChainELBuilder {
} }
public void build() { public void build() {
// 如果不用是新的chain不需要更新
if (chain.isExist()) {
return;
} else {
// 如果是新的chain需要更新
if (StrUtil.isNotBlank(chain.getEl())){
chain.setChainSha256();
}
}
this.chain.setRouteItem(this.route); this.chain.setRouteItem(this.route);
this.chain.setConditionList(this.conditionList); this.chain.setConditionList(this.conditionList);

View File

@ -2,7 +2,6 @@ package com.yomahub.liteflow.enums;
public enum ScriptTypeEnum { public enum ScriptTypeEnum {
CUSTOM("custom", "custom"),
GROOVY("groovy", "groovy"), GROOVY("groovy", "groovy"),
QLEXPRESS("qlexpress", "qlexpress"), QLEXPRESS("qlexpress", "qlexpress"),
JS("javascript", "js"), JS("javascript", "js"),

View File

@ -10,199 +10,228 @@ package com.yomahub.liteflow.flow.element;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import com.yomahub.liteflow.exception.ChainEndException; import com.yomahub.liteflow.exception.ChainEndException;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLog;
import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.log.LFLoggerManager;
import com.yomahub.liteflow.slot.DataBus; import com.yomahub.liteflow.slot.DataBus;
import com.yomahub.liteflow.slot.Slot; import com.yomahub.liteflow.slot.Slot;
import com.yomahub.liteflow.enums.ExecuteableTypeEnum; import com.yomahub.liteflow.enums.ExecuteableTypeEnum;
import com.yomahub.liteflow.exception.FlowSystemException; import com.yomahub.liteflow.exception.FlowSystemException;
import com.yomahub.liteflow.util.Sha256Util;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Optional;
/** /**
* chain对象实现可执行器 * chain对象实现可执行器
* *
* @author Bryan.Zhang * @author Bryan.Zhang
*/ */
public class Chain implements Executable{ public class Chain implements Executable {
private static final LFLog LOG = LFLoggerManager.getLogger(Chain.class); private static final LFLog LOG = LFLoggerManager.getLogger(Chain.class);
private String chainId; private String chainId;
private Executable routeItem; private String chainSha256;
private List<Condition> conditionList = new ArrayList<>(); private Executable routeItem;
private String el; private List<Condition> conditionList = new ArrayList<>();
private boolean isCompiled = true; private String el;
private String namespace; private boolean isCompiled = true;
public Chain(String chainName) { private String namespace;
this.chainId = chainName;
}
public Chain() { public Chain(String chainName) {
} this.chainId = chainName;
}
public Chain(String chainName, List<Condition> conditionList) { public Chain() {
this.chainId = chainName; }
this.conditionList = conditionList;
}
public List<Condition> getConditionList() { public Chain(String chainName, List<Condition> conditionList) {
return conditionList; this.chainId = chainName;
} this.conditionList = conditionList;
}
public void setConditionList(List<Condition> conditionList) { public List<Condition> getConditionList() {
this.conditionList = conditionList; return conditionList;
} }
/** public void setConditionList(List<Condition> conditionList) {
* @deprecated 请使用{@link #getChainId()} this.conditionList = conditionList;
*/ }
@Deprecated
public String getChainName() {
return chainId;
}
/** /**
* @param chainName * @deprecated 请使用{@link #getChainId()}
* @deprecated 请使用 {@link #setChainId(String)} */
*/ @Deprecated
public void setChainName(String chainName) { public String getChainName() {
this.chainId = chainName; return chainId;
} }
public String getChainId() { /**
return chainId; * @param chainName
} * @deprecated 请使用 {@link #setChainId(String)}
*/
public void setChainName(String chainName) {
this.chainId = chainName;
}
public void setChainId(String chainId) { public String getChainId() {
this.chainId = chainId; return chainId;
} }
// 执行chain的主方法 public void setChainId(String chainId) {
@Override this.chainId = chainId;
public void execute(Integer slotIndex) throws Exception { }
if (BooleanUtil.isFalse(isCompiled)) {
LiteFlowChainELBuilder.buildUnCompileChain(this);
}
if (CollUtil.isEmpty(conditionList)) { // 执行chain的主方法
throw new FlowSystemException("no conditionList in this chain[" + chainId + "]"); @Override
} public void execute(Integer slotIndex) throws Exception {
Slot slot = DataBus.getSlot(slotIndex); if (BooleanUtil.isFalse(isCompiled)) {
try { LiteFlowChainELBuilder.buildUnCompileChain(this);
// 设置主ChainName }
slot.setChainId(chainId);
// 执行主体Condition
for (Condition condition : conditionList) {
condition.setCurrChainId(chainId);
condition.execute(slotIndex);
}
}
catch (ChainEndException e) {
// 这里单独catch ChainEndException是因为ChainEndException是用户自己setIsEnd抛出的异常
// 是属于正常逻辑所以会在FlowExecutor中判断这里不作为异常处理
throw e;
}
catch (Exception e) {
// 这里事先取到exception set到slot里为了方便finally取到exception
if (slot.isSubChain(chainId)) {
slot.setSubException(chainId, e);
}
else {
slot.setException(e);
}
throw e;
}
}
public void executeRoute(Integer slotIndex) throws Exception { if (CollUtil.isEmpty(conditionList)) {
if (routeItem == null) { throw new FlowSystemException("no conditionList in this chain[" + chainId + "]");
throw new FlowSystemException("no route condition or node in this chain[" + chainId + "]"); }
} Slot slot = DataBus.getSlot(slotIndex);
Slot slot = DataBus.getSlot(slotIndex); try {
try { // 设置主ChainName
// 设置主ChainName slot.setChainId(chainId);
slot.setChainId(chainId); // 执行主体Condition
for (Condition condition : conditionList) {
condition.setCurrChainId(chainId);
condition.execute(slotIndex);
}
} catch (ChainEndException e) {
// 这里单独catch ChainEndException是因为ChainEndException是用户自己setIsEnd抛出的异常
// 是属于正常逻辑所以会在FlowExecutor中判断这里不作为异常处理
throw e;
} catch (Exception e) {
// 这里事先取到exception set到slot里为了方便finally取到exception
if (slot.isSubChain(chainId)) {
slot.setSubException(chainId, e);
} else {
slot.setException(e);
}
throw e;
}
}
// 执行决策路由 public void executeRoute(Integer slotIndex) throws Exception {
routeItem.setCurrChainId(chainId); if (routeItem == null) {
routeItem.execute(slotIndex); throw new FlowSystemException("no route condition or node in this chain[" + chainId + "]");
}
Slot slot = DataBus.getSlot(slotIndex);
try {
// 设置主ChainName
slot.setChainId(chainId);
boolean routeResult = routeItem.getItemResultMetaValue(slotIndex); // 执行决策路由
routeItem.setCurrChainId(chainId);
routeItem.execute(slotIndex);
slot.setRouteResult(routeResult); boolean routeResult = routeItem.getItemResultMetaValue(slotIndex);
}
catch (ChainEndException e) {
throw e;
}
catch (Exception e) {
slot.setException(e);
throw e;
}
}
@Override slot.setRouteResult(routeResult);
public ExecuteableTypeEnum getExecuteType() { } catch (ChainEndException e) {
return ExecuteableTypeEnum.CHAIN; throw e;
} } catch (Exception e) {
slot.setException(e);
throw e;
}
}
@Override @Override
public void setId(String id) { public ExecuteableTypeEnum getExecuteType() {
this.chainId = id; return ExecuteableTypeEnum.CHAIN;
} }
@Override @Override
public String getId() { public void setId(String id) {
return chainId; this.chainId = id;
} }
@Override @Override
public void setTag(String tag) { public String getId() {
//do nothing return chainId;
} }
@Override @Override
public String getTag() { public void setTag(String tag) {
return null; //do nothing
} }
public Executable getRouteItem() { @Override
return routeItem; public String getTag() {
} return null;
}
public void setRouteItem(Executable routeItem) { public Executable getRouteItem() {
this.routeItem = routeItem; return routeItem;
} }
public String getEl() { public void setRouteItem(Executable routeItem) {
return el; this.routeItem = routeItem;
} }
public void setEl(String el) { public String getEl() {
this.el = el; return el;
} }
public boolean isCompiled() { public void setEl(String el) {
return isCompiled; this.el = el;
} }
public void setCompiled(boolean compiled) { public boolean isCompiled() {
isCompiled = compiled; return isCompiled;
} }
public String getNamespace() { public void setCompiled(boolean compiled) {
return namespace; isCompiled = compiled;
} }
public void setNamespace(String namespace) { public String getNamespace() {
this.namespace = namespace; return namespace;
} }
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public String getChainSha256() {
return chainSha256;
}
public void setChainSha256() {
String ns = Optional.ofNullable(this.namespace).orElse("");
this.chainSha256 = Sha256Util.sha256(chainId + ns + el);
}
public boolean isExist() {
if (StrUtil.isBlank(chainId) || StrUtil.isBlank(el)) {
return false;
}
String ns = Optional.ofNullable(this.namespace).orElse("");
String elSha256 = Sha256Util.sha256(chainId + ns + el);
for (Chain chainElement : FlowBus.getChainMap().values()) {
String chainSha256Exist = chainElement.getChainSha256();
if (Objects.equals(chainSha256Exist, elSha256)) {
return true;
}
}
return false;
}
} }

View File

@ -15,6 +15,29 @@ import java.util.List;
*/ */
public class NodeConvertHelper { public class NodeConvertHelper {
/*script节点的修改/添加*/
public static void changeScriptNode(NodeSimpleVO nodeSimpleVO, String newValue) {
// 有语言类型
if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) {
LiteFlowNodeBuilder.createScriptNode()
.setId(nodeSimpleVO.getNodeId())
.setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType()))
.setName(nodeSimpleVO.getName())
.setScript(newValue)
.setLanguage(nodeSimpleVO.getLanguage())
.build();
}
// 没有语言类型
else {
LiteFlowNodeBuilder.createScriptNode()
.setId(nodeSimpleVO.getNodeId())
.setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType()))
.setName(nodeSimpleVO.getName())
.setScript(newValue)
.build();
}
}
public static NodeSimpleVO convert(String scriptKey){ public static NodeSimpleVO convert(String scriptKey){
// 不需要去理解这串正则就是一个匹配冒号的 // 不需要去理解这串正则就是一个匹配冒号的
// 一定得是a:b或是a:b:c...这种完整类型的字符串的 // 一定得是a:b或是a:b:c...这种完整类型的字符串的

View File

@ -0,0 +1,33 @@
package com.yomahub.liteflow.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* sha 256 工具类
*
* @author gaibu
* @since 2.12.1
*/
public class Sha256Util {
public static String sha256(String input) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(input.getBytes());
// Convert byte array to hexadecimal string
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -13,7 +13,7 @@
type (script|boolean_script|switch_script|for_script) #IMPLIED type (script|boolean_script|switch_script|for_script) #IMPLIED
class CDATA #IMPLIED class CDATA #IMPLIED
file CDATA #IMPLIED file CDATA #IMPLIED
language (qlexpress|groovy|js|python|lua|aviator|java|kotlin) #IMPLIED language (qlexpress|groovy|js|python|lua|aviator|java) #IMPLIED
enable (true|false) #IMPLIED enable (true|false) #IMPLIED
> >
<!ATTLIST chain <!ATTLIST chain

View File

@ -16,7 +16,7 @@ public class SqlReadConstant {
public static final String SCRIPT_SQL_PATTERN = "SELECT * FROM {} WHERE {}=?"; public static final String SCRIPT_SQL_PATTERN = "SELECT * FROM {} WHERE {}=?";
public static final String CHAIN_XML_PATTERN = "<chain id=\"{}\" namespace=\"{}\"><route><![CDATA[{}]]></route><body><![CDATA[{}]]></body></chain>"; public static final String CHAIN_XML_PATTERN = "<chain name=\"{}\"><![CDATA[{}]]></chain>";
public static final String NODE_XML_PATTERN = "<nodes>{}</nodes>"; public static final String NODE_XML_PATTERN = "<nodes>{}</nodes>";

View File

@ -11,8 +11,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
/** /**
* sql 轮询任务抽象类维护公共方法 * sql 轮询任务抽象类维护公共方法
@ -21,11 +19,11 @@ import java.util.stream.Collectors;
* @author houxinyu * @author houxinyu
* @since 2.11.1 * @since 2.11.1
*/ */
public abstract class AbstractSqlReadPollTask<T> implements SqlReadPollTask<T> { public abstract class AbstractSqlReadPollTask implements SqlReadPollTask {
private final Map<String/*唯一键*/, String/*data-xml的sha1值*/> DATA_SHA_MAP = new HashMap<>(); private final Map<String/*唯一键*/, String/*data-xml的sha1值*/> DATA_SHA_MAP = new HashMap<>();
private final SqlRead<T> read; private final SqlRead read;
public AbstractSqlReadPollTask(SqlRead<T> read) { public AbstractSqlReadPollTask(SqlRead read) {
this.read = read; this.read = read;
if (!read.type().equals(type())) { if (!read.type().equals(type())) {
@ -35,34 +33,35 @@ public abstract class AbstractSqlReadPollTask<T> implements SqlReadPollTask<T> {
@Override @Override
public void execute() { public void execute() {
List<T> dataList = read.read(); Map<String/*唯一键*/, String/*data-xml*/> newData = read.read();
// 新增或者更新的元素 // 新增或者更新的元素
List<T> saveElementList = new ArrayList<>(); Map<String, String> saveElementMap = new HashMap<>();
// 删除的元素 // 删除的元素
List<String> deleteElementIds; List<String> deleteElementIds = new ArrayList<>();
for (T data : dataList) { for (Map.Entry<String, String> entry : newData.entrySet()) {
String id = getKey(data); String id = entry.getKey();
String newSHA = getNeedSha1Value(data); String element = entry.getValue();
String newSHA = DigestUtil.sha1Hex(element);
// 新增 // 新增
// 如果封装的SHAMap中不存在该chain, 表示该元素为新增 // 如果封装的SHAMap中不存在该chain, 表示该元素为新增
if (!DATA_SHA_MAP.containsKey(id)) { if (!DATA_SHA_MAP.containsKey(id)) {
saveElementList.add(data); saveElementMap.put(id, element);
DATA_SHA_MAP.put(id, newSHA); DATA_SHA_MAP.put(id, newSHA);
} }
// 修改 // 修改
// SHA值发生变化,表示该元素的值已被修改,重新拉取变化的chain // SHA值发生变化,表示该元素的值已被修改,重新拉取变化的chain
else if (!StrUtil.equals(newSHA, DATA_SHA_MAP.get(id))) { else if (!StrUtil.equals(newSHA, DATA_SHA_MAP.get(id))) {
saveElementList.add(data); saveElementMap.put(id, element);
DATA_SHA_MAP.put(id, newSHA); DATA_SHA_MAP.put(id, newSHA);
} }
} }
Set<String> oldIdList = DATA_SHA_MAP.keySet(); // 旧的 id 列表 Set<String> oldIdList = DATA_SHA_MAP.keySet(); // 旧的 id 列表
Set<String> newIdList = dataList.stream().map(this::getKey).collect(Collectors.toSet()); // 新的 id 列表 Set<String> newIdList = newData.keySet(); // 新的 id 列表
// 计算单差集 // 计算单差集
// 计算集合的单差集即只返回oldIdList中有但是newIdList中没有的元素例如 // 计算集合的单差集即只返回oldIdList中有但是newIdList中没有的元素例如
// subtractToList([1,2,3,4],[2,3,4,5]) - [1] // subtractToList([1,2,3,4],[2,3,4,5]) - [1]
@ -72,8 +71,8 @@ public abstract class AbstractSqlReadPollTask<T> implements SqlReadPollTask<T> {
DATA_SHA_MAP.remove(id); DATA_SHA_MAP.remove(id);
} }
if (CollUtil.isNotEmpty(saveElementList)) { if (CollUtil.isNotEmpty(saveElementMap)) {
doSave(saveElementList); doSave(saveElementMap);
} }
if (CollUtil.isNotEmpty(deleteElementIds)) { if (CollUtil.isNotEmpty(deleteElementIds)) {
@ -82,34 +81,20 @@ public abstract class AbstractSqlReadPollTask<T> implements SqlReadPollTask<T> {
} }
@Override @Override
public void initData(List<T> dataList) { public void initData(Map<String/*唯一键*/, String/*data-xml的数据*/> dataMap) {
DATA_SHA_MAP.putAll(shaValue(dataList)); DATA_SHA_MAP.putAll(shaMapValue(dataMap));
} }
public abstract void doSave(List<T> saveElementList); public abstract void doSave(Map<String, String> saveElementMap);
public abstract void doDelete(List<String> deleteElementId); public abstract void doDelete(List<String> deleteElementId);
private Map<String/*唯一键*/, String/*data-xml的sha1值*/> shaValue(List<T> dataList) { private Map<String/*唯一键*/, String/*data-xml的sha1值*/> shaMapValue(Map<String, String> dataMap) {
Map<String, String> result = new HashMap<>(); Map<String, String> result = new HashMap<>();
dataList.forEach(t -> result.put(getKey(t), DigestUtil.sha1Hex(getNeedSha1Value(t)))); dataMap.forEach((k, v) -> {
result.put(k, DigestUtil.sha1Hex(v));
});
return result; return result;
} }
private String getNeedSha1Value(T data) {
if (StrUtil.isBlank(getExtValue(data))) {
return DigestUtil.sha1Hex(getValue(data));
}else{
return DigestUtil.sha1Hex(getValue(data) + "|||" + getExtValue(data));
}
}
// 如果是chain那就是返回chain的id如果是script那就返回script的id
protected abstract String getKey(T t);
// 如果是chain那就返回EL如果是script那就返回脚本数据
protected abstract String getValue(T t);
// 如果是chain那就返回route el如果是script这个不返回因为script没有扩展value
protected abstract String getExtValue(T t);
} }

View File

@ -2,7 +2,6 @@ package com.yomahub.liteflow.parser.sql.polling;
import com.yomahub.liteflow.parser.constant.ReadType; import com.yomahub.liteflow.parser.constant.ReadType;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -12,7 +11,7 @@ import java.util.Map;
* @author houxinyu * @author houxinyu
* @since 2.11.1 * @since 2.11.1
*/ */
public interface SqlReadPollTask<T> { public interface SqlReadPollTask {
/** /**
* 执行 * 执行
@ -22,8 +21,9 @@ public interface SqlReadPollTask<T> {
/** /**
* 初始化数据 * 初始化数据
* *
* @param dataMap 数据
*/ */
void initData(List<T> dataList); void initData(Map<String/*唯一键*/, String/*data-xml的数据*/> dataMap);
/** /**
* 类型 * 类型

View File

@ -1,16 +1,13 @@
package com.yomahub.liteflow.parser.sql.polling.impl; package com.yomahub.liteflow.parser.sql.polling.impl;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.parser.constant.ReadType; import com.yomahub.liteflow.parser.constant.ReadType;
import com.yomahub.liteflow.parser.sql.polling.AbstractSqlReadPollTask; import com.yomahub.liteflow.parser.sql.polling.AbstractSqlReadPollTask;
import com.yomahub.liteflow.parser.sql.read.SqlRead; import com.yomahub.liteflow.parser.sql.read.SqlRead;
import com.yomahub.liteflow.parser.sql.read.vo.ChainVO;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer;
/** /**
* chain 读取任务 * chain 读取任务
@ -19,20 +16,20 @@ import java.util.function.Consumer;
* @author houxinyu * @author houxinyu
* @since 2.11.1 * @since 2.11.1
*/ */
public class ChainReadPollTask extends AbstractSqlReadPollTask<ChainVO> { public class ChainReadPollTask extends AbstractSqlReadPollTask {
public ChainReadPollTask(SqlRead<ChainVO> read) { public ChainReadPollTask(SqlRead read) {
super(read); super(read);
} }
@Override @Override
public void doSave(List<ChainVO> saveElementList) { public void doSave(Map<String, String> saveElementMap) {
saveElementList.forEach(chainVO -> for (Map.Entry<String, String> entry : saveElementMap.entrySet()) {
LiteFlowChainELBuilder.createChain().setChainId(chainVO.getChainId()) String chainName = entry.getKey();
.setRoute(chainVO.getRoute()) String newData = entry.getValue();
.setNamespace(chainVO.getNamespace())
.setEL(chainVO.getBody()) LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newData).build();
.build()); }
} }
@Override @Override
@ -42,21 +39,6 @@ public class ChainReadPollTask extends AbstractSqlReadPollTask<ChainVO> {
} }
} }
@Override
protected String getKey(ChainVO chainVO) {
return chainVO.getChainId();
}
@Override
protected String getValue(ChainVO chainVO) {
return chainVO.getBody();
}
@Override
protected String getExtValue(ChainVO chainVO) {
return chainVO.getRoute();
}
@Override @Override
public ReadType type() { public ReadType type() {
return ReadType.CHAIN; return ReadType.CHAIN;

View File

@ -1,18 +1,13 @@
package com.yomahub.liteflow.parser.sql.polling.impl; package com.yomahub.liteflow.parser.sql.polling.impl;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.parser.constant.ReadType; import com.yomahub.liteflow.parser.constant.ReadType;
import com.yomahub.liteflow.parser.helper.NodeConvertHelper; import com.yomahub.liteflow.parser.helper.NodeConvertHelper;
import com.yomahub.liteflow.parser.sql.polling.AbstractSqlReadPollTask; import com.yomahub.liteflow.parser.sql.polling.AbstractSqlReadPollTask;
import com.yomahub.liteflow.parser.sql.read.SqlRead; import com.yomahub.liteflow.parser.sql.read.SqlRead;
import com.yomahub.liteflow.parser.sql.read.vo.ScriptVO;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer;
/** /**
* 脚本轮询任务 * 脚本轮询任务
@ -21,45 +16,32 @@ import java.util.function.Consumer;
* @author houxinyu * @author houxinyu
* @since 2.11.1 * @since 2.11.1
*/ */
public class ScriptReadPollTask extends AbstractSqlReadPollTask<ScriptVO> { public class ScriptReadPollTask extends AbstractSqlReadPollTask {
public ScriptReadPollTask(SqlRead<ScriptVO> read) { public ScriptReadPollTask(SqlRead read) {
super(read); super(read);
} }
@Override @Override
public void doSave(List<ScriptVO> saveElementList) { public void doSave(Map<String, String> saveElementMap) {
saveElementList.forEach(scriptVO -> LiteFlowNodeBuilder.createScriptNode() for (Map.Entry<String, String> entry : saveElementMap.entrySet()) {
.setId(scriptVO.getNodeId()) String scriptKey = entry.getKey();
.setType(NodeTypeEnum.getEnumByCode(scriptVO.getType())) String newData = entry.getValue();
.setName(scriptVO.getName())
.setScript(scriptVO.getScript()) NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey);
.setLanguage(scriptVO.getLanguage()) NodeConvertHelper.changeScriptNode(scriptVO, newData);
.build()); }
} }
@Override @Override
public void doDelete(List<String> deleteElementId) { public void doDelete(List<String> deleteElementId) {
for (String id : deleteElementId) { for (String id : deleteElementId) {
NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(id);
// 删除script // 删除script
FlowBus.unloadScriptNode(id); FlowBus.unloadScriptNode(scriptVO.getNodeId());
} }
} }
@Override
protected String getKey(ScriptVO scriptVO) {
return scriptVO.getNodeId();
}
@Override
protected String getValue(ScriptVO scriptVO) {
return scriptVO.getScript();
}
@Override
protected String getExtValue(ScriptVO scriptVO) {
return StrUtil.EMPTY;
}
@Override @Override
public ReadType type() { public ReadType type() {
return ReadType.SCRIPT; return ReadType.SCRIPT;

View File

@ -9,9 +9,7 @@ import com.yomahub.liteflow.parser.sql.util.LiteFlowJdbcUtil;
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
import java.sql.*; import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -22,7 +20,7 @@ import java.util.Map;
* @author Bryan.Zhang * @author Bryan.Zhang
* @since 2.11.1 * @since 2.11.1
*/ */
public abstract class AbstractSqlRead<T> implements SqlRead<T> { public abstract class AbstractSqlRead implements SqlRead {
public final SQLParserVO config; public final SQLParserVO config;
private static LFLog LOG = LFLoggerManager.getLogger(AbstractSqlRead.class); private static LFLog LOG = LFLoggerManager.getLogger(AbstractSqlRead.class);
@ -31,10 +29,10 @@ public abstract class AbstractSqlRead<T> implements SqlRead<T> {
} }
@Override @Override
public List<T> read() { public Map<String/*规则唯一键*/, String/*规则内容*/> read() {
// 如果不需要读取直接返回 // 如果不需要读取直接返回
if (!needRead()) { if (!needRead()) {
return new ArrayList<>(); return new HashMap<>();
} }
checkConfig(); checkConfig();
@ -42,7 +40,7 @@ public abstract class AbstractSqlRead<T> implements SqlRead<T> {
// 如果允许就打印 sql 语句 // 如果允许就打印 sql 语句
logSqlIfEnable(sqlCmd); logSqlIfEnable(sqlCmd);
List<T> result = new ArrayList<>(); Map<String/*规则唯一键*/, String/*规则*/> result = new HashMap<>();
Connection conn = null; Connection conn = null;
PreparedStatement stmt = null; PreparedStatement stmt = null;
ResultSet rs = null; ResultSet rs = null;
@ -56,6 +54,9 @@ public abstract class AbstractSqlRead<T> implements SqlRead<T> {
rs = stmt.executeQuery(); rs = stmt.executeQuery();
while (rs.next()) { while (rs.next()) {
String xml = buildXmlElement(rs);
String uniqueKey = buildXmlElementUniqueKey(rs);
if (hasEnableFiled()){ if (hasEnableFiled()){
boolean enable = getEnableFiledValue(rs); boolean enable = getEnableFiledValue(rs);
// 如果停用直接跳过 // 如果停用直接跳过
@ -63,7 +64,7 @@ public abstract class AbstractSqlRead<T> implements SqlRead<T> {
continue; continue;
} }
} }
result.add(parse(rs)); result.put(uniqueKey, xml);
} }
} catch (Exception e) { } catch (Exception e) {
throw new ELSQLException(e.getMessage()); throw new ELSQLException(e.getMessage());
@ -75,8 +76,6 @@ public abstract class AbstractSqlRead<T> implements SqlRead<T> {
return result; return result;
} }
protected abstract T parse(ResultSet rs) throws SQLException;
/** /**
* 是否包含启停字段 * 是否包含启停字段
*/ */
@ -89,6 +88,10 @@ public abstract class AbstractSqlRead<T> implements SqlRead<T> {
public abstract String buildQuerySql(); public abstract String buildQuerySql();
public abstract String buildXmlElement(ResultSet rs) throws SQLException;
public abstract String buildXmlElementUniqueKey(ResultSet rs) throws SQLException;
public abstract void checkConfig(); public abstract void checkConfig();
/** /**

View File

@ -2,7 +2,6 @@ package com.yomahub.liteflow.parser.sql.read;
import com.yomahub.liteflow.parser.constant.ReadType; import com.yomahub.liteflow.parser.constant.ReadType;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -12,14 +11,14 @@ import java.util.Map;
* @author houxinyu * @author houxinyu
* @since 2.11.1 * @since 2.11.1
*/ */
public interface SqlRead<T> { public interface SqlRead {
/** /**
* 读取 * 读取
* *
* @return 返回读取到的数据 * @return 返回读取到的数据
*/ */
List<T> read(); Map<String/*规则唯一键*/, String/*规则内容*/> read();
/** /**
* 类型 * 类型

View File

@ -19,30 +19,28 @@ import java.util.Map;
* @since 2.11.1 * @since 2.11.1
*/ */
public class SqlReadFactory { public class SqlReadFactory {
private static final Map<ReadType, SqlRead<?>> READ_MAP = new HashMap<>(); private static final Map<ReadType, SqlRead> READ_MAP = new HashMap<>();
private static final Map<ReadType, SqlReadPollTask<?>> POLL_TASK_MAP = new HashMap<>(); private static final Map<ReadType, SqlReadPollTask> POLL_TASK_MAP = new HashMap<>();
public static void registerRead(SQLParserVO config) { public static void registerRead(SQLParserVO config) {
READ_MAP.put(ReadType.CHAIN, new ChainRead(config)); READ_MAP.putIfAbsent(ReadType.CHAIN, new ChainRead(config));
READ_MAP.put(ReadType.SCRIPT, new ScriptRead(config)); READ_MAP.putIfAbsent(ReadType.SCRIPT, new ScriptRead(config));
} }
public static void registerSqlReadPollTask(ReadType readType) { public static void registerSqlReadPollTask(ReadType readType) {
SqlRead<?> sqlRead = getSqlRead(readType); SqlRead sqlRead = getSqlRead(readType);
if (ReadType.CHAIN.equals(readType)) { if (ReadType.CHAIN.equals(readType)) {
POLL_TASK_MAP.put(ReadType.CHAIN, new ChainReadPollTask((ChainRead)sqlRead)); POLL_TASK_MAP.putIfAbsent(ReadType.CHAIN, new ChainReadPollTask(sqlRead));
} else if (ReadType.SCRIPT.equals(readType)) { } else if (ReadType.SCRIPT.equals(readType)) {
POLL_TASK_MAP.put(ReadType.SCRIPT, new ScriptReadPollTask((ScriptRead)sqlRead)); POLL_TASK_MAP.putIfAbsent(ReadType.SCRIPT, new ScriptReadPollTask(sqlRead));
} }
} }
@SuppressWarnings("unchecked") public static SqlRead getSqlRead(ReadType readType) {
public static <T> SqlRead<T> getSqlRead(ReadType readType) { return READ_MAP.get(readType);
return (SqlRead<T>)READ_MAP.get(readType);
} }
@SuppressWarnings("unchecked") public static SqlReadPollTask getSqlReadPollTask(ReadType readType) {
public static <T> SqlReadPollTask<T> getSqlReadPollTask(ReadType readType) { return POLL_TASK_MAP.get(readType);
return (SqlReadPollTask<T>)POLL_TASK_MAP.get(readType);
} }
} }

View File

@ -5,7 +5,6 @@ import com.yomahub.liteflow.parser.constant.ReadType;
import com.yomahub.liteflow.parser.constant.SqlReadConstant; import com.yomahub.liteflow.parser.constant.SqlReadConstant;
import com.yomahub.liteflow.parser.sql.exception.ELSQLException; import com.yomahub.liteflow.parser.sql.exception.ELSQLException;
import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead; import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead;
import com.yomahub.liteflow.parser.sql.read.vo.ChainVO;
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -18,26 +17,12 @@ import java.sql.SQLException;
* @author houxinyu * @author houxinyu
* @since 2.11.1 * @since 2.11.1
*/ */
public class ChainRead extends AbstractSqlRead<ChainVO> { public class ChainRead extends AbstractSqlRead {
public ChainRead(SQLParserVO config) { public ChainRead(SQLParserVO config) {
super(config); super(config);
} }
@Override
protected ChainVO parse(ResultSet rs) throws SQLException {
ChainVO chainVO = new ChainVO();
chainVO.setChainId(getStringFromRsWithCheck(rs, super.config.getChainNameField()));
chainVO.setBody(getStringFromRsWithCheck(rs, super.config.getElDataField()));
if (StrUtil.isNotBlank(super.config.getNamespaceField())){
chainVO.setNamespace(getStringFromRs(rs, super.config.getNamespaceField()));
}
if (StrUtil.isNotBlank(super.config.getRouteField())){
chainVO.setRoute(getStringFromRs(rs, super.config.getRouteField()));
}
return chainVO;
}
@Override @Override
public boolean hasEnableFiled() { public boolean hasEnableFiled() {
String chainEnableField = super.config.getChainEnableField(); String chainEnableField = super.config.getChainEnableField();
@ -85,6 +70,20 @@ public class ChainRead extends AbstractSqlRead<ChainVO> {
} }
} }
@Override
public String buildXmlElement(ResultSet rs) throws SQLException {
String elDataField = super.config.getElDataField();
return getStringFromRs(rs, elDataField);
}
@Override
public String buildXmlElementUniqueKey(ResultSet rs) throws SQLException {
String chainNameField = super.config.getChainNameField();
return getStringFromRsWithCheck(rs, chainNameField);
}
@Override @Override
public ReadType type() { public ReadType type() {
return ReadType.CHAIN; return ReadType.CHAIN;

View File

@ -8,7 +8,6 @@ import com.yomahub.liteflow.parser.constant.ReadType;
import com.yomahub.liteflow.parser.constant.SqlReadConstant; import com.yomahub.liteflow.parser.constant.SqlReadConstant;
import com.yomahub.liteflow.parser.sql.exception.ELSQLException; import com.yomahub.liteflow.parser.sql.exception.ELSQLException;
import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead; import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead;
import com.yomahub.liteflow.parser.sql.read.vo.ScriptVO;
import com.yomahub.liteflow.parser.sql.util.LiteFlowJdbcUtil; import com.yomahub.liteflow.parser.sql.util.LiteFlowJdbcUtil;
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
@ -25,23 +24,12 @@ import java.util.Objects;
* @author houxinyu * @author houxinyu
* @since 2.11.1 * @since 2.11.1
*/ */
public class ScriptRead extends AbstractSqlRead<ScriptVO> { public class ScriptRead extends AbstractSqlRead {
public ScriptRead(SQLParserVO config) { public ScriptRead(SQLParserVO config) {
super(config); super(config);
} }
@Override
protected ScriptVO parse(ResultSet rs) throws SQLException {
ScriptVO scriptVO = new ScriptVO();
scriptVO.setNodeId(getStringFromRsWithCheck(rs, super.config.getScriptIdField()));
scriptVO.setName(getStringFromRs(rs, super.config.getScriptNameField()));
scriptVO.setType(getStringFromRsWithCheck(rs, super.config.getScriptTypeField()));
scriptVO.setLanguage(getStringFromRs(rs, super.config.getScriptLanguageField()));
scriptVO.setScript(getStringFromRsWithCheck(rs, super.config.getScriptDataField()));
return scriptVO;
}
@Override @Override
public boolean hasEnableFiled() { public boolean hasEnableFiled() {
String scriptEnableField = super.config.getScriptEnableField(); String scriptEnableField = super.config.getScriptEnableField();
@ -92,6 +80,46 @@ public class ScriptRead extends AbstractSqlRead<ScriptVO> {
} }
} }
@Override
public String buildXmlElement(ResultSet rs) throws SQLException {
String scriptDataField = super.config.getScriptDataField();
return getStringFromRs(rs, scriptDataField);
}
@Override
public String buildXmlElementUniqueKey(ResultSet rs) throws SQLException {
String scriptIdField = super.config.getScriptIdField();
String scriptNameField = super.config.getScriptNameField();
String scriptTypeField = super.config.getScriptTypeField();
String scriptLanguageField = super.config.getScriptLanguageField();
String id = getStringFromRsWithCheck(rs, scriptIdField);
String name = getStringFromRsWithCheck(rs, scriptNameField);
String type = getStringFromRsWithCheck(rs, scriptTypeField);
String language = withLanguage() ? getStringFromRs(rs, scriptLanguageField) : null;
NodeTypeEnum nodeTypeEnum = NodeTypeEnum.getEnumByCode(type);
if (Objects.isNull(nodeTypeEnum)) {
throw new ELSQLException(StrUtil.format("Invalid type value[{}]", type));
}
if (!nodeTypeEnum.isScript()) {
throw new ELSQLException(StrUtil.format("The type value[{}] is not a script type", type));
}
if (withLanguage() && !ScriptTypeEnum.checkScriptType(language)) {
throw new ELSQLException(StrUtil.format("The language value[{}] is invalid", language));
}
List<String> keys = CollUtil.newArrayList(id, type, name);
if (StrUtil.isNotBlank(language)) {
keys.add(language);
}
return StrUtil.join(StrUtil.COLON, keys);
}
@Override @Override
public boolean needRead() { public boolean needRead() {
if (StrUtil.isBlank(super.config.getScriptTableName())) { if (StrUtil.isBlank(super.config.getScriptTableName())) {

View File

@ -1,44 +0,0 @@
package com.yomahub.liteflow.parser.sql.read.vo;
public class ChainVO {
private String chainId;
private String route;
private String namespace;
private String body;
public String getChainId() {
return chainId;
}
public void setChainId(String chainId) {
this.chainId = chainId;
}
public String getRoute() {
return route;
}
public void setRoute(String route) {
this.route = route;
}
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}

View File

@ -1,64 +0,0 @@
package com.yomahub.liteflow.parser.sql.read.vo;
public class ScriptVO {
private String nodeId;
private String type;
private String name;
private String language;
private Boolean enable;
private String script;
public String getNodeId() {
return nodeId;
}
public void setNodeId(String nodeId) {
this.nodeId = nodeId;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public Boolean getEnable() {
return enable;
}
public void setEnable(Boolean enable) {
this.enable = enable;
}
public String getScript() {
return script;
}
public void setScript(String script) {
this.script = script;
}
}

View File

@ -11,12 +11,9 @@ import com.yomahub.liteflow.parser.constant.ReadType;
import com.yomahub.liteflow.parser.helper.NodeConvertHelper; import com.yomahub.liteflow.parser.helper.NodeConvertHelper;
import com.yomahub.liteflow.parser.sql.exception.ELSQLException; import com.yomahub.liteflow.parser.sql.exception.ELSQLException;
import com.yomahub.liteflow.parser.sql.polling.SqlReadPollTask;
import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead; import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead;
import com.yomahub.liteflow.parser.sql.read.SqlRead; import com.yomahub.liteflow.parser.sql.read.SqlRead;
import com.yomahub.liteflow.parser.sql.read.SqlReadFactory; import com.yomahub.liteflow.parser.sql.read.SqlReadFactory;
import com.yomahub.liteflow.parser.sql.read.vo.ChainVO;
import com.yomahub.liteflow.parser.sql.read.vo.ScriptVO;
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
@ -90,30 +87,30 @@ public class JDBCHelper {
* @return 数据内容 * @return 数据内容
*/ */
public String getContent() { public String getContent() {
SqlRead<ChainVO> chainRead = SqlReadFactory.getSqlRead(ReadType.CHAIN); SqlRead chainRead = SqlReadFactory.getSqlRead(ReadType.CHAIN);
SqlRead<ScriptVO> scriptRead = SqlReadFactory.getSqlRead(ReadType.SCRIPT); SqlRead scriptRead = SqlReadFactory.getSqlRead(ReadType.SCRIPT);
// 获取 chain 数据 // 获取 chain 数据
List<ChainVO> chainVOList = chainRead.read(); Map<String, String> chainMap = chainRead.read();
List<String> chainList = new ArrayList<>(); List<String> chainList = new ArrayList<>();
chainVOList.forEach( chainMap.entrySet().stream()
chainVO -> chainList.add(StrUtil.format(CHAIN_XML_PATTERN, XmlUtil.escape(chainVO.getChainId()), StrUtil.emptyIfNull(chainVO.getNamespace()), StrUtil.emptyIfNull(chainVO.getRoute()), chainVO.getBody())) .filter(entry -> StrUtil.isNotBlank(entry.getValue()))
); .forEach(
entry -> chainList.add(StrUtil.format(CHAIN_XML_PATTERN, XmlUtil.escape(entry.getKey()), entry.getValue()))
);
String chainsContent = CollUtil.join(chainList, StrUtil.EMPTY); String chainsContent = CollUtil.join(chainList, StrUtil.EMPTY);
// 获取脚本数据 // 获取脚本数据
List<ScriptVO> scriptVOList = scriptRead.read(); Map<String, String> scriptMap = scriptRead.read();
List<String> scriptList = new ArrayList<>(); List<String> scriptList = new ArrayList<>();
scriptMap.forEach((scriptKey, elData) -> {
scriptVOList.forEach(scriptVO -> { NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey);
String id = scriptVO.getNodeId(); String id = scriptVO.getNodeId();
String name = scriptVO.getName(); String name = scriptVO.getName();
String type = scriptVO.getType(); String type = scriptVO.getType();
String language = scriptVO.getLanguage(); String language = scriptVO.getLanguage();
String elData = scriptVO.getScript();
if (StringUtils.isNotBlank(scriptVO.getLanguage())) { if (StringUtils.isNotBlank(scriptVO.getLanguage())) {
scriptList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, language, elData)); scriptList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, language, elData));
@ -121,14 +118,11 @@ public class JDBCHelper {
scriptList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, elData)); scriptList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, elData));
} }
}); });
String nodesContent = StrUtil.format(NODE_XML_PATTERN, CollUtil.join(scriptList, StrUtil.EMPTY)); String nodesContent = StrUtil.format(NODE_XML_PATTERN, CollUtil.join(scriptList, StrUtil.EMPTY));
// 初始化轮询任务 // 初始化轮询任务
SqlReadPollTask<ChainVO> sqlReadPollTask4Chain = SqlReadFactory.getSqlReadPollTask(ReadType.CHAIN); SqlReadFactory.getSqlReadPollTask(ReadType.CHAIN).initData(chainMap);
sqlReadPollTask4Chain.initData(chainVOList); SqlReadFactory.getSqlReadPollTask(ReadType.SCRIPT).initData(scriptMap);
SqlReadPollTask<ScriptVO> sqlReadPollTask4Script = SqlReadFactory.getSqlReadPollTask(ReadType.SCRIPT);
sqlReadPollTask4Script.initData(scriptVOList);
return StrUtil.format(XML_PATTERN, nodesContent, chainsContent); return StrUtil.format(XML_PATTERN, nodesContent, chainsContent);
} }

View File

@ -56,16 +56,6 @@ public class SQLParserVO {
*/ */
private String elDataField = "el_data"; private String elDataField = "el_data";
/**
* 决策路由字段
*/
private String routeField;
/**
* 命名空间字段
*/
private String namespaceField;
/** /**
* 是否启动某一条chain * 是否启动某一条chain
*/ */
@ -320,20 +310,4 @@ public class SQLParserVO {
public boolean hasEnableField() { public boolean hasEnableField() {
return StrUtil.isNotBlank(chainEnableField) || StrUtil.isNotBlank(scriptEnableField); return StrUtil.isNotBlank(chainEnableField) || StrUtil.isNotBlank(scriptEnableField);
} }
public String getRouteField() {
return routeField;
}
public void setRouteField(String routeField) {
this.routeField = routeField;
}
public String getNamespaceField() {
return namespaceField;
}
public void setNamespaceField(String namespaceField) {
this.namespaceField = namespaceField;
}
} }

View File

@ -13,7 +13,7 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf; import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -65,7 +65,7 @@ public class AbsoluteConfigPathELDeclMultiSpringbootTest extends BaseTest {
} }
@Test @Test
@EnabledIf("isWindows") @DisabledIf("isWindows")
public void testAbsPath() throws Exception{ public void testAbsPath() throws Exception{
Assertions.assertTrue(() -> { Assertions.assertTrue(() -> {
LiteflowConfig config = LiteflowConfigGetter.get(); LiteflowConfig config = LiteflowConfigGetter.get();
@ -80,7 +80,7 @@ public class AbsoluteConfigPathELDeclMultiSpringbootTest extends BaseTest {
String osName = System.getProperty("os.name"); String osName = System.getProperty("os.name");
if (osName.isEmpty()) return false; if (osName.isEmpty()) return false;
else { else {
return osName.contains("Windows"); return osName.contains("windows");
} }
} catch (Exception e) { } catch (Exception e) {
return false; return false;

View File

@ -15,7 +15,7 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf; import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -67,7 +67,7 @@ public class AbsoluteConfigPathELDeclSpringbootTest extends BaseTest {
} }
@Test @Test
@EnabledIf("isWindows") @DisabledIf("isWindows")
public void testAbsPath() throws Exception{ public void testAbsPath() throws Exception{
Assertions.assertTrue(() -> { Assertions.assertTrue(() -> {
LiteflowConfig config = LiteflowConfigGetter.get(); LiteflowConfig config = LiteflowConfigGetter.get();
@ -82,7 +82,7 @@ public class AbsoluteConfigPathELDeclSpringbootTest extends BaseTest {
String osName = System.getProperty("os.name"); String osName = System.getProperty("os.name");
if (osName.isEmpty()) return false; if (osName.isEmpty()) return false;
else { else {
return osName.contains("Windows"); return osName.contains("windows");
} }
} catch (Exception e) { } catch (Exception e) {
return false; return false;

View File

@ -14,7 +14,7 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf; import org.junit.jupiter.api.condition.DisabledIf;
import java.util.Objects; import java.util.Objects;
@ -52,7 +52,7 @@ public class AbsoluteConfigPathTest extends BaseTest {
} }
@Test @Test
@EnabledIf("isWindows") @DisabledIf("isWindows")
public void testAbsPath() throws Exception{ public void testAbsPath() throws Exception{
Assertions.assertTrue(() -> { Assertions.assertTrue(() -> {
LiteflowConfig config = new LiteflowConfig(); LiteflowConfig config = new LiteflowConfig();
@ -67,7 +67,7 @@ public class AbsoluteConfigPathTest extends BaseTest {
String osName = System.getProperty("os.name"); String osName = System.getProperty("os.name");
if (osName.isEmpty()) return false; if (osName.isEmpty()) return false;
else { else {
return osName.contains("Windows"); return osName.contains("windows");
} }
} catch (Exception e) { } catch (Exception e) {
return false; return false;

View File

@ -6,7 +6,9 @@ import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.core.FlowExecutorHolder; import com.yomahub.liteflow.core.FlowExecutorHolder;
import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.exception.ELParseException; import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.flow.element.Chain;
import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.test.BaseTest; import com.yomahub.liteflow.test.BaseTest;
import com.yomahub.liteflow.test.builder.cmp.*; import com.yomahub.liteflow.test.builder.cmp.*;
@ -175,4 +177,45 @@ public class BuilderTest extends BaseTest {
Assertions.assertEquals("a1[组件A1]==>c2[组件C2]==>a2[组件A2]==>c1[组件C1]", response.getExecuteStepStr()); Assertions.assertEquals("a1[组件A1]==>c2[组件C2]==>a2[组件A2]==>c1[组件C1]", response.getExecuteStepStr());
} }
// 测试 EL 表达式的覆盖
@Test
public void testBuilderElOver() throws Exception {
LiteFlowNodeBuilder.createNode()
.setId("a1")
.setName("组件A1")
.setType(NodeTypeEnum.COMMON)
.setClazz(ACmp.class)
.build();
LiteFlowNodeBuilder.createNode()
.setId("a2")
.setName("组件A2")
.setType(NodeTypeEnum.COMMON)
.setClazz(ACmp.class)
.build();
LiteFlowNodeBuilder.createNode()
.setId("c1")
.setName("组件C1")
.setType(NodeTypeEnum.COMMON)
.setClazz(CCmp.class)
.build();
LiteFlowNodeBuilder.createNode()
.setId("c2")
.setName("组件C2")
.setType(NodeTypeEnum.COMMON)
.setClazz(CCmp.class)
.build();
LiteFlowChainELBuilder.createChain().setChainName("chain1").setEL("THEN(a1,c2,a2,c1)").build();
String sha256 = FlowBus.getChainMap().get("chain1").getChainSha256();
LiteFlowChainELBuilder.createChain().setChainId("chain1").setEL("THEN(a1,c2,a2,c1)").build();
String sha256Same = FlowBus.getChainMap().get("chain1").getChainSha256();
Assertions.assertEquals(sha256, sha256Same);
LiteFlowChainELBuilder.createChain().setChainId("chain1").setEL("THEN(a1,c2,a2)").build();
String chain1Sha256 = FlowBus.getChainMap().get("chain1").getChainSha256();
Assertions.assertNotEquals(sha256, chain1Sha256);
}
} }

View File

@ -172,7 +172,7 @@ public class FallbackTest extends BaseTest {
LiteflowResponse response = flowExecutor.execute2Resp("concurrent2", "arg"); LiteflowResponse response = flowExecutor.execute2Resp("concurrent2", "arg");
Assertions.assertTrue(response.isSuccess()); Assertions.assertTrue(response.isSuccess());
String stepStr = response.getExecuteStepStrWithoutTime(); String stepStr = response.getExecuteStepStrWithoutTime();
Assertions.assertTrue("fb_comm_cmp==>fb_bool_cmp".equals(stepStr) || "fb_bool_cmp==>fb_comm_cmp".equals(stepStr)); Assertions.assertTrue("fb_comm_cmp==>fb_bool_cmp".equals(stepStr) || "ifn2==>c".equals(stepStr));
} }
@Test @Test

View File

@ -13,7 +13,7 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf; import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.noear.solon.annotation.Inject; import org.noear.solon.annotation.Inject;
import org.noear.solon.test.SolonJUnit5Extension; import org.noear.solon.test.SolonJUnit5Extension;
@ -58,7 +58,7 @@ public class AbsoluteConfigPathELSpringbootTest extends BaseTest {
} }
@Test @Test
@EnabledIf("isWindows") @DisabledIf("isWindows")
public void testAbsTest() throws Exception { public void testAbsTest() throws Exception {
Assertions.assertTrue(() -> { Assertions.assertTrue(() -> {
LiteflowConfig config = LiteflowConfigGetter.get(); LiteflowConfig config = LiteflowConfigGetter.get();
@ -73,7 +73,7 @@ public class AbsoluteConfigPathELSpringbootTest extends BaseTest {
String osName = System.getProperty("os.name"); String osName = System.getProperty("os.name");
if (osName.isEmpty()) return false; if (osName.isEmpty()) return false;
else { else {
return osName.contains("Windows"); return osName.contains("windows");
} }
} catch (Exception e) { } catch (Exception e) {
return false; return false;

View File

@ -13,7 +13,7 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf; import org.junit.jupiter.api.condition.DisabledIf;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -72,7 +72,7 @@ public class AbsoluteConfigPathELSpringbootTest extends BaseTest {
} }
@Test @Test
@EnabledIf("isWindows") @DisabledIf("isWindows")
public void testAbsPath4() throws Exception{ public void testAbsPath4() throws Exception{
Assertions.assertTrue(() -> { Assertions.assertTrue(() -> {
LiteflowConfig config = LiteflowConfigGetter.get(); LiteflowConfig config = LiteflowConfigGetter.get();
@ -87,7 +87,7 @@ public class AbsoluteConfigPathELSpringbootTest extends BaseTest {
String osName = System.getProperty("os.name"); String osName = System.getProperty("os.name");
if (osName.isEmpty()) return false; if (osName.isEmpty()) return false;
else { else {
return osName.contains("Windows"); return osName.contains("windows");
} }
} catch (Exception e) { } catch (Exception e) {
return false; return false;

View File

@ -13,7 +13,7 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf; import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
@ -57,7 +57,7 @@ public class AbsoluteConfigPathELSpringTest extends BaseTest {
} }
@Test @Test
@EnabledIf("isWindows") @DisabledIf("isWindows")
public void testAbsPath() throws Exception{ public void testAbsPath() throws Exception{
Assertions.assertTrue(() -> { Assertions.assertTrue(() -> {
LiteflowConfig config = LiteflowConfigGetter.get(); LiteflowConfig config = LiteflowConfigGetter.get();
@ -72,7 +72,7 @@ public class AbsoluteConfigPathELSpringTest extends BaseTest {
String osName = System.getProperty("os.name"); String osName = System.getProperty("os.name");
if (osName.isEmpty()) return false; if (osName.isEmpty()) return false;
else { else {
return osName.contains("Windows"); return osName.contains("windows");
} }
} catch (Exception e) { } catch (Exception e) {
return false; return false;

View File

@ -1,56 +0,0 @@
package com.yomahub.liteflow.test.sqlroute;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.parser.sql.exception.ELSQLException;
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import com.yomahub.liteflow.slot.DefaultContext;
import com.yomahub.liteflow.test.BaseTest;
import com.yomahub.liteflow.util.JsonUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.function.Predicate;
/**
* @author tangkc
* @since 2.9.0
*/
@ExtendWith(SpringExtension.class)
@TestPropertySource(value = "classpath:/application-route.properties")
@SpringBootTest(classes = SQLRouteSpringbootTest.class)
@EnableAutoConfiguration
@ComponentScan({ "com.yomahub.liteflow.test.sqlroute.cmp" })
public class SQLRouteSpringbootTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
@Test
public void testRoute1() {
List<LiteflowResponse> responseList = flowExecutor.executeRouteChain("ns", 15, DefaultContext.class);
LiteflowResponse response1 = responseList.stream().filter(liteflowResponse -> liteflowResponse.getChainId().equals("r_chain1")).findFirst().orElse(null);
Assertions.assertTrue(response1.isSuccess());
Assertions.assertEquals("a==>b==>c", response1.getExecuteStepStr());
LiteflowResponse response2 = responseList.stream().filter(liteflowResponse -> liteflowResponse.getChainId().equals("r_chain2")).findFirst().orElse(null);
Assertions.assertTrue(response2.isSuccess());
Assertions.assertEquals("c==>b==>a", response2.getExecuteStepStr());
}
}

View File

@ -1,21 +0,0 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.sqlroute.cmp;
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
System.out.println("ACmp executed!");
}
}

View File

@ -1,21 +0,0 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.sqlroute.cmp;
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;
@Component("b")
public class BCmp extends NodeComponent {
@Override
public void process() {
System.out.println("BCmp executed!");
}
}

View File

@ -1,21 +0,0 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.sqlroute.cmp;
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;
@Component("c")
public class CCmp extends NodeComponent {
@Override
public void process() {
System.out.println("CCmp executed!");
}
}

View File

@ -1,13 +0,0 @@
package com.yomahub.liteflow.test.sqlroute.cmp;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeBooleanComponent;
@LiteflowComponent("r1")
public class R1 extends NodeBooleanComponent {
@Override
public boolean processBoolean() throws Exception {
int testInt = this.getRequestData();
return testInt >= 10 && testInt <= 20;
}
}

View File

@ -1,13 +0,0 @@
package com.yomahub.liteflow.test.sqlroute.cmp;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeBooleanComponent;
@LiteflowComponent("r2")
public class R2 extends NodeBooleanComponent {
@Override
public boolean processBoolean() throws Exception {
int testInt = this.getRequestData();
return testInt > 100;
}
}

View File

@ -1,28 +0,0 @@
liteflow.rule-source-ext-data={\
"url":"jdbc:h2:mem:test_db;MODE=MySQL",\
"driverClassName":"org.h2.Driver",\
"username":"root",\
"password":"123456",\
"applicationName":"demo",\
"chainTableName":"EL_TABLE",\
"chainApplicationNameField":"application_name",\
"chainNameField":"chain_name",\
"elDataField":"EL_DATA",\
"routeField":"route",\
"namespaceField":"namespace",\
"scriptTableName":"script_node_table",\
"scriptApplicationNameField":"application_name",\
"scriptIdField":"script_node_id",\
"scriptNameField":"script_node_name",\
"scriptDataField":"script_node_data",\
"scriptLanguageField":"script_language",\
"scriptTypeField":"script_node_type"\
}
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:test_db;MODE=MySQL
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.schema=classpath:/sql/schema.sql
spring.datasource.data=classpath:/sql/data.sql
spring.datasource.platform=h2

View File

@ -5,8 +5,6 @@ INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain
INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain3','IF(x0, THEN(a, b));'); INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain3','IF(x0, THEN(a, b));');
INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','<chain3>','IF(x0, THEN(a, b));'); INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','<chain3>','IF(x0, THEN(a, b));');
INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain4','IF(x2, IF(x0, THEN(a, b)));'); INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain4','IF(x2, IF(x0, THEN(a, b)));');
INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA,ROUTE,NAMESPACE) values ('demo','r_chain1','THEN(a,b,c);','r1','ns');
INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA,ROUTE,NAMESPACE) values ('demo','r_chain2','THEN(c,b,a);','OR(r1,r2)','ns');
DELETE FROM SCRIPT_NODE_TABLE; DELETE FROM SCRIPT_NODE_TABLE;

View File

@ -4,8 +4,6 @@ create table IF NOT EXISTS `EL_TABLE`
`application_name` varchar(32) NOT NULL, `application_name` varchar(32) NOT NULL,
`chain_name` varchar(32) NOT NULL, `chain_name` varchar(32) NOT NULL,
`el_data` varchar(1024) NOT NULL, `el_data` varchar(1024) NOT NULL,
`route` varchar(1024),
`namespace` varchar(32),
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
); );

View File

@ -39,7 +39,7 @@
</scm> </scm>
<properties> <properties>
<revision>2.12.1</revision> <revision>2.12.0</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>8</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
@ -394,6 +394,10 @@
</goals> </goals>
</execution> </execution>
</executions> </executions>
<configuration>
<!-- 默认不使用 gpg ,如果需要使用请在打包命令中增加 -Dgpg.skip=false -->
<skip>true</skip>
</configuration>
</plugin> </plugin>
<!-- version number --> <!-- version number -->
<plugin> <plugin>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 327 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 188 KiB