From d5966f09c6e8953c4a07bfa95c3ea2f8c0e52d05 Mon Sep 17 00:00:00 2001 From: bryan31 Date: Mon, 9 Aug 2021 00:54:06 +0800 Subject: [PATCH] =?UTF-8?q?feature=20#I44FT8=20=E6=94=AF=E6=8C=81=E8=84=9A?= =?UTF-8?q?=E6=9C=AC=E8=AF=AD=E8=A8=80=E7=9A=84=E7=BB=84=E4=BB=B6=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E6=94=AF=E6=8C=81=E5=8A=A8=E6=80=81=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E8=84=9A=E6=9C=AC(=E7=89=88=E6=9C=AC=E7=89=B9=E6=80=A7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- liteflow-core/pom.xml | 6 ++ .../liteflow/core/ScriptNodeComponent.java | 20 +++++++ .../yomahub/liteflow/entity/flow/Node.java | 1 + .../com/yomahub/liteflow/flow/FlowBus.java | 18 +++++- .../liteflow/parser/XmlFlowParser.java | 34 ++++++++---- liteflow-script-common/pom.xml | 26 +++++++++ .../liteflow/script/ScriptExecutor.java | 15 +++++ .../liteflow/script/ScriptFactory.java | 30 ++++++++++ .../exception/ScriptExecuteException.java | 27 +++++++++ .../script/exception/ScriptLoadException.java | 27 +++++++++ liteflow-script-qlexpress/pom.xml | 31 +++++++++++ .../qlexpress/QLExpressScriptExecutor.java | 55 +++++++++++++++++++ ...com.yomahub.liteflow.script.ScriptExecutor | 0 pom.xml | 15 +++++ 14 files changed, 291 insertions(+), 14 deletions(-) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptNodeComponent.java create mode 100644 liteflow-script-common/pom.xml create mode 100644 liteflow-script-common/src/main/java/com/yomahub/liteflow/script/ScriptExecutor.java create mode 100644 liteflow-script-common/src/main/java/com/yomahub/liteflow/script/ScriptFactory.java create mode 100644 liteflow-script-common/src/main/java/com/yomahub/liteflow/script/exception/ScriptExecuteException.java create mode 100644 liteflow-script-common/src/main/java/com/yomahub/liteflow/script/exception/ScriptLoadException.java create mode 100644 liteflow-script-qlexpress/pom.xml create mode 100644 liteflow-script-qlexpress/src/main/java/com/yomahub/liteflow/script/qlexpress/QLExpressScriptExecutor.java create mode 100644 liteflow-script-qlexpress/src/main/resources/com.yomahub.liteflow.script.ScriptExecutor diff --git a/liteflow-core/pom.xml b/liteflow-core/pom.xml index d4f317d96..2b907e482 100644 --- a/liteflow-core/pom.xml +++ b/liteflow-core/pom.xml @@ -13,6 +13,12 @@ + + com.yomahub + liteflow-script-common + ${project.version} + + cn.hutool hutool-core diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptNodeComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptNodeComponent.java new file mode 100644 index 000000000..7d7c322af --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptNodeComponent.java @@ -0,0 +1,20 @@ +package com.yomahub.liteflow.core; + +import com.yomahub.liteflow.script.ScriptFactory; + +/** + * 脚本组件类 + * @author Bryan.Zhang + * @since 2.5.11 + */ +public class ScriptNodeComponent extends NodeComponent{ + + @Override + public void process() throws Exception { + ScriptFactory.loadInstance().getScriptExecutor().execute(getNodeId(), getSlotIndex()); + } + + public void loadScript(String script) { + ScriptFactory.loadInstance().getScriptExecutor().load(getNodeId(), script); + } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Node.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Node.java index 5d284cb0b..285b98c39 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Node.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Node.java @@ -14,6 +14,7 @@ import java.util.Map; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.core.ScriptNodeComponent; import com.yomahub.liteflow.entity.data.DataBus; import com.yomahub.liteflow.entity.data.Slot; import com.yomahub.liteflow.enums.ExecuteTypeEnum; diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java index c84b41b71..7b2e4d558 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java @@ -12,6 +12,7 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.core.ScriptNodeComponent; import com.yomahub.liteflow.entity.flow.Chain; import com.yomahub.liteflow.entity.flow.Node; import com.yomahub.liteflow.enums.FlowParserTypeEnum; @@ -23,6 +24,7 @@ import com.yomahub.liteflow.util.SpringAware; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; @@ -72,14 +74,19 @@ public class FlowBus { public static void addNode(String nodeId, String name, String cmpClazzStr) throws Exception { if (containNode(nodeId)) return; Class cmpClazz = (Class) Class.forName(cmpClazzStr); - addNode(nodeId, name ,cmpClazz); + addNode(nodeId, name ,cmpClazz, null); + } + + public static void addScriptNode(String nodeId, String name, String script){ + if (containNode(nodeId)) return; + addNode(nodeId, name , ScriptNodeComponent.class, script); } public static void addNode(String nodeId, Class cmpClazz){ - addNode(nodeId, null, cmpClazz); + addNode(nodeId, null, cmpClazz, null); } - public static void addNode(String nodeId, String name, Class cmpClazz) { + public static void addNode(String nodeId, String name, Class cmpClazz, String script) { if (containNode(nodeId)) return; try { //以node方式配置,本质上是为了适配无spring的环境,如果有spring环境,其实不用这么配置 @@ -92,6 +99,11 @@ public class FlowBus { cmpInstance.setNodeId(nodeId); cmpInstance.setName(name); cmpInstance.setSelf(cmpInstance); + + //如果是脚本节点,则还要加载script脚本 + if (cmpClazz.equals(ScriptNodeComponent.class) && StrUtil.isNotBlank(script)){ + ((ScriptNodeComponent)cmpInstance).loadScript(script); + } nodeMap.put(nodeId, new Node(cmpInstance)); } catch (Exception e) { String error = StrUtil.format("component[{}] register error", cmpClazz.getName()); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java index aca934c10..a9ad0bcb9 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.parser; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.common.LocalDefaultFlowConstant; import com.yomahub.liteflow.core.NodeComponent; @@ -52,23 +53,34 @@ public abstract class XmlFlowParser extends FlowParser { //xml形式的主要解析过程 public void parseDocument(List documentList) throws Exception { try { + //先进行Spring上下文中的节点的判断 + for (Entry componentEntry : ComponentScanner.nodeComponentMap.entrySet()) { + if (!FlowBus.containNode(componentEntry.getKey())) { + FlowBus.addNode(componentEntry.getKey(), new Node(componentEntry.getValue())); + } + } + for (Document document : documentList) { Element rootElement = document.getRootElement(); - //判断是以spring方式注册节点,还是以xml方式注册 - if (ComponentScanner.nodeComponentMap.isEmpty()) { - // 解析node节点 - List nodeList = rootElement.element("nodes").elements("node"); - String id, name, clazz; + Element nodesElement = rootElement.element("nodes"); + // 当存在节点定义时,解析node节点 + if (ObjectUtil.isNotNull(nodesElement)){ + List nodeList = nodesElement.elements("node"); + String id, name, clazz, script; for (Element e : nodeList) { id = e.attributeValue("id"); name = e.attributeValue("name"); clazz = e.attributeValue("class"); - FlowBus.addNode(id, name, clazz); - } - } else { - for (Entry componentEntry : ComponentScanner.nodeComponentMap.entrySet()) { - if (!FlowBus.containNode(componentEntry.getKey())) { - FlowBus.addNode(componentEntry.getKey(), new Node(componentEntry.getValue())); + + if (StrUtil.isNotBlank(clazz)){ + if (!FlowBus.containNode(id)){ + FlowBus.addNode(id, name, clazz); + } + }else{ + if (!FlowBus.containNode(id)){ + script = e.getTextTrim(); + FlowBus.addScriptNode(id, name, script); + } } } } diff --git a/liteflow-script-common/pom.xml b/liteflow-script-common/pom.xml new file mode 100644 index 000000000..d45d0dc0b --- /dev/null +++ b/liteflow-script-common/pom.xml @@ -0,0 +1,26 @@ + + + + liteflow + com.yomahub + 2.5.11 + + 4.0.0 + + liteflow-script-common + + + + org.springframework + spring-beans + true + + + cn.hutool + hutool-core + true + + + \ No newline at end of file diff --git a/liteflow-script-common/src/main/java/com/yomahub/liteflow/script/ScriptExecutor.java b/liteflow-script-common/src/main/java/com/yomahub/liteflow/script/ScriptExecutor.java new file mode 100644 index 000000000..a38a2de26 --- /dev/null +++ b/liteflow-script-common/src/main/java/com/yomahub/liteflow/script/ScriptExecutor.java @@ -0,0 +1,15 @@ +package com.yomahub.liteflow.script; + +/** + * 脚本执行器 + * @author Bryan.Zhang + * @since 2.5.11 + */ +public interface ScriptExecutor { + + ScriptExecutor init(); + + void load(String nodeId, String script); + + void execute(String nodeId, int slotIndex); +} diff --git a/liteflow-script-common/src/main/java/com/yomahub/liteflow/script/ScriptFactory.java b/liteflow-script-common/src/main/java/com/yomahub/liteflow/script/ScriptFactory.java new file mode 100644 index 000000000..38e398b79 --- /dev/null +++ b/liteflow-script-common/src/main/java/com/yomahub/liteflow/script/ScriptFactory.java @@ -0,0 +1,30 @@ +package com.yomahub.liteflow.script; + +import cn.hutool.core.util.ObjectUtil; + +import java.util.ServiceLoader; + +public class ScriptFactory { + + private static ScriptFactory scriptFactory; + + private static ScriptExecutor scriptExecutor; + + public static ScriptFactory loadInstance(){ + if (ObjectUtil.isNull(scriptFactory)){ + scriptFactory = new ScriptFactory(); + } + return scriptFactory; + } + + public ScriptExecutor getScriptExecutor(){ + if (ObjectUtil.isNull(scriptExecutor)){ + ServiceLoader loader = ServiceLoader.load(ScriptExecutor.class); + if (loader.iterator().hasNext()){ + scriptExecutor = loader.iterator().next().init(); + return scriptExecutor; + } + } + return scriptExecutor; + } +} diff --git a/liteflow-script-common/src/main/java/com/yomahub/liteflow/script/exception/ScriptExecuteException.java b/liteflow-script-common/src/main/java/com/yomahub/liteflow/script/exception/ScriptExecuteException.java new file mode 100644 index 000000000..d8b1d4d92 --- /dev/null +++ b/liteflow-script-common/src/main/java/com/yomahub/liteflow/script/exception/ScriptExecuteException.java @@ -0,0 +1,27 @@ + +package com.yomahub.liteflow.script.exception; + +/** + * 脚本运行异常 + * @author Bryan.Zhang + * @since 2.5.11 + */ +public class ScriptExecuteException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** 异常信息 */ + private String message; + + public ScriptExecuteException(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/liteflow-script-common/src/main/java/com/yomahub/liteflow/script/exception/ScriptLoadException.java b/liteflow-script-common/src/main/java/com/yomahub/liteflow/script/exception/ScriptLoadException.java new file mode 100644 index 000000000..8fcf609f0 --- /dev/null +++ b/liteflow-script-common/src/main/java/com/yomahub/liteflow/script/exception/ScriptLoadException.java @@ -0,0 +1,27 @@ + +package com.yomahub.liteflow.script.exception; + +/** + * 脚本加载异常 + * @author Bryan.Zhang + * @since 2.5.11 + */ +public class ScriptLoadException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** 异常信息 */ + private String message; + + public ScriptLoadException(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/liteflow-script-qlexpress/pom.xml b/liteflow-script-qlexpress/pom.xml new file mode 100644 index 000000000..78bc08320 --- /dev/null +++ b/liteflow-script-qlexpress/pom.xml @@ -0,0 +1,31 @@ + + + + liteflow + com.yomahub + 2.5.11 + + 4.0.0 + + liteflow-script-qlexpress + + + + com.yomahub + liteflow-script-common + ${project.version} + + + com.yomahub + liteflow-core + ${project.version} + true + + + com.alibaba + QLExpress + + + \ No newline at end of file diff --git a/liteflow-script-qlexpress/src/main/java/com/yomahub/liteflow/script/qlexpress/QLExpressScriptExecutor.java b/liteflow-script-qlexpress/src/main/java/com/yomahub/liteflow/script/qlexpress/QLExpressScriptExecutor.java new file mode 100644 index 000000000..29b11a33f --- /dev/null +++ b/liteflow-script-qlexpress/src/main/java/com/yomahub/liteflow/script/qlexpress/QLExpressScriptExecutor.java @@ -0,0 +1,55 @@ +package com.yomahub.liteflow.script.qlexpress; + +import cn.hutool.core.util.StrUtil; +import com.ql.util.express.DefaultContext; +import com.ql.util.express.ExpressRunner; +import com.yomahub.liteflow.entity.data.DataBus; +import com.yomahub.liteflow.entity.data.Slot; +import com.yomahub.liteflow.script.ScriptExecutor; +import com.yomahub.liteflow.script.exception.ScriptExecuteException; +import com.yomahub.liteflow.script.exception.ScriptLoadException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +public class QLExpressScriptExecutor implements ScriptExecutor { + + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + private ExpressRunner expressRunner; + + @Override + public ScriptExecutor init() { + expressRunner = new ExpressRunner(); + return this; + } + + @Override + public void load(String nodeId, String script) { + try{ + expressRunner.loadMutilExpress(nodeId, script); + }catch (Exception e){ + String errorMsg = StrUtil.format("script loading error for node[{}]", nodeId); + throw new ScriptLoadException(errorMsg); + } + } + + @Override + public void execute(String nodeId, int slotIndex) { + List errorList = new ArrayList<>(); + try{ + Slot slot = DataBus.getSlot(slotIndex); + DefaultContext context = new DefaultContext(); + context.put("slot", slot); + expressRunner.executeByExpressName(nodeId, context, errorList, true, false, null); + }catch (Exception e){ + for (String scriptErrorMsg : errorList){ + log.error("\n{}", scriptErrorMsg); + } + String errorMsg = StrUtil.format("script execute error for node[{}]", nodeId); + throw new ScriptExecuteException(errorMsg); + } + } +} diff --git a/liteflow-script-qlexpress/src/main/resources/com.yomahub.liteflow.script.ScriptExecutor b/liteflow-script-qlexpress/src/main/resources/com.yomahub.liteflow.script.ScriptExecutor new file mode 100644 index 000000000..e69de29bb diff --git a/pom.xml b/pom.xml index 4ed275f5b..73ca42d5a 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,8 @@ 2.12.1 5.1.0 0.10 + 3.2.0 + 3.0.8 @@ -150,6 +152,17 @@ zkclient ${zkclient.version} + + + com.alibaba + QLExpress + ${qlexpress.version} + + + org.codehaus.groovy + groovy-all + ${groovy.version} + @@ -229,6 +242,8 @@ liteflow-core liteflow-spring-boot-starter + liteflow-script-qlexpress + liteflow-script-common