From daa65d0d0ebebee3fe14094f79e25a37a4ea4987 Mon Sep 17 00:00:00 2001 From: "everywhere.z" Date: Tue, 26 Jul 2022 00:51:05 +0800 Subject: [PATCH] =?UTF-8?q?feature=20#I5IA5U=20=E6=8F=90=E4=BE=9B=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E5=8C=85=E8=A3=85=E8=AF=AD=E6=B3=95+=E6=9B=BF?= =?UTF-8?q?=E8=A1=A5=E8=8A=82=E7=82=B9=E7=9A=84=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0el=E8=A1=A8=E8=BE=BE=E5=BC=8F=E6=9D=A5?= =?UTF-8?q?=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/el/LiteFlowChainELBuilder.java | 1 + .../builder/el/operator/NodeOperator.java | 65 +++++++++++++++++++ .../liteflow/property/LiteflowConfig.java | 11 ++++ .../liteflow/springboot/LiteflowProperty.java | 11 ++++ .../LiteflowPropertyAutoConfiguration.java | 1 + ...itional-spring-configuration-metadata.json | 7 ++ .../META-INF/liteflow-default.properties | 1 + .../SubstituteSpringbootTest.java | 44 +++++++++++++ .../test/substituteNode/cmp/ACmp.java | 20 ++++++ .../test/substituteNode/cmp/BCmp.java | 21 ++++++ .../test/substituteNode/cmp/CCmp.java | 21 ++++++ .../test/substituteNode/cmp/SubCmp.java | 21 ++++++ .../substituteNode/application.properties | 2 + .../test/resources/substituteNode/flow.el.xml | 10 +++ 14 files changed, 236 insertions(+) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/application.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/flow.el.xml diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java index 440e5b1ad..0b7568746 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java @@ -66,6 +66,7 @@ public class LiteFlowChainELBuilder { expressRunner.addFunctionAndClassMethod("id", Object.class, new IdOperator()); expressRunner.addFunctionAndClassMethod("ignoreError", Object.class, new IgnoreErrorOperator()); expressRunner.addFunctionAndClassMethod("threadPool", Object.class, new ThreadPoolOperator()); + expressRunner.addFunction("node", new NodeOperator()); } //在parser中chain的build是2段式的,因为涉及到依赖问题,以前是递归parser diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java new file mode 100644 index 000000000..88b61f073 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java @@ -0,0 +1,65 @@ +package com.yomahub.liteflow.builder.el.operator; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.ql.util.express.Operator; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.flow.element.Node; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.function.Predicate; + +/** + * EL规则中的node的操作符 + * @author Bryan.Zhang + * @since 2.8.3 + */ +public class NodeOperator extends Operator { + + private final Logger LOG = LoggerFactory.getLogger(this.getClass()); + + @Override + public Object executeInner(Object[] objects) throws Exception { + if (ArrayUtil.isEmpty(objects)){ + throw new Exception(); + } + + if (objects.length != 1){ + LOG.error("parameter error"); + throw new Exception(); + } + + String nodeId; + if (objects[0] instanceof String){ + nodeId = (String) objects[0]; + }else{ + LOG.error("The value must be Node item!"); + throw new Exception(); + } + + if (FlowBus.containNode(nodeId)){ + return FlowBus.getNode(nodeId); + }else{ + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + if (StrUtil.isNotBlank(liteflowConfig.getSubstituteCmpClass())){ + Node substituteNode = FlowBus.getNodeMap().values().stream().filter(node + -> node.getInstance().getClass().getName().equals(liteflowConfig.getSubstituteCmpClass())).findFirst().orElse(null); + if (ObjectUtil.isNotNull(substituteNode)){ + return substituteNode; + }else{ + String error = StrUtil.format("This node[{}] cannot be found", nodeId); + LOG.error(error); + throw new Exception(); + } + }else{ + String error = StrUtil.format("This node[{}] cannot be found, or you can configure an substitute node", nodeId); + LOG.error(error); + throw new Exception(); + } + } + } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java index f320c6d3a..f50d8f46c 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java @@ -87,6 +87,9 @@ public class LiteflowConfig { //是否打印执行中的日志 private Boolean printExecutionLog; + //替补组件class路径 + private String substituteCmpClass; + public Boolean getEnable() { if (ObjectUtil.isNull(enable)) { return Boolean.TRUE; @@ -333,4 +336,12 @@ public class LiteflowConfig { public void setPrintExecutionLog(Boolean printExecutionLog) { this.printExecutionLog = printExecutionLog; } + + public String getSubstituteCmpClass() { + return substituteCmpClass; + } + + public void setSubstituteCmpClass(String substituteCmpClass) { + this.substituteCmpClass = substituteCmpClass; + } } diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java index 9fb6cd20b..1ad21adcc 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java @@ -62,6 +62,9 @@ public class LiteflowProperty { //是否打印执行过程中的日志 private boolean printExecutionLog; + //替补组件的class路径 + private String substituteCmpClass; + public boolean isEnable() { return enable; } @@ -197,4 +200,12 @@ public class LiteflowProperty { public void setRequestIdGeneratorClass(String requestIdGeneratorClass) { this.requestIdGeneratorClass = requestIdGeneratorClass; } + + public String getSubstituteCmpClass() { + return substituteCmpClass; + } + + public void setSubstituteCmpClass(String substituteCmpClass) { + this.substituteCmpClass = substituteCmpClass; + } } diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowPropertyAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowPropertyAutoConfiguration.java index eaca85a5f..80986b4bf 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowPropertyAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowPropertyAutoConfiguration.java @@ -45,6 +45,7 @@ public class LiteflowPropertyAutoConfiguration { liteflowConfig.setMainExecutorWorks(property.getMainExecutorWorks()); liteflowConfig.setMainExecutorClass(property.getMainExecutorClass()); liteflowConfig.setPrintExecutionLog(property.isPrintExecutionLog()); + liteflowConfig.setSubstituteCmpClass(property.getSubstituteCmpClass()); return liteflowConfig; } } diff --git a/liteflow-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/liteflow-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 3cdaf349e..51b0a3324 100644 --- a/liteflow-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/liteflow-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -119,6 +119,13 @@ "sourceType": "com.yomahub.liteflow.springboot.LiteflowProperty", "defaultValue": true }, + { + "name": "liteflow.substitute-cmp-class", + "type": "java.lang.String", + "description": "substitute component class.", + "sourceType": "com.yomahub.liteflow.springboot.LiteflowProperty", + "defaultValue": "" + }, { "name": "liteflow.monitor.enable-log", "type": "java.lang.Boolean", diff --git a/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties b/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties index 582418ad2..50264318f 100644 --- a/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties +++ b/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties @@ -14,6 +14,7 @@ liteflow.retry-count=0 liteflow.support-multiple-type=false liteflow.node-executor-class=com.yomahub.liteflow.flow.executor.DefaultNodeExecutor liteflow.print-execution-log=true +liteflow.substitute-cmp-class= liteflow.monitor.enable-log=false liteflow.monitor.queue-limit=200 liteflow.monitor.delay=300000 diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java new file mode 100644 index 000000000..bdec0acd9 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java @@ -0,0 +1,44 @@ +package com.yomahub.liteflow.test.substituteNode; + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.test.BaseTest; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +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.junit4.SpringRunner; + +import javax.annotation.Resource; + +/** + * springboot环境EL替补节点的测试 + * @author Bryan.Zhang + */ +@RunWith(SpringRunner.class) +@TestPropertySource(value = "classpath:/substituteNode/application.properties") +@SpringBootTest(classes = SubstituteSpringbootTest.class) +@EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.substituteNode.cmp"}) +public class SubstituteSpringbootTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + //最简单的情况 + @Test + public void testSub1() throws Exception{ + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assert.assertTrue(response.isSuccess()); + } + + //有替补节点 + @Test + public void testSub2() throws Exception{ + LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); + Assert.assertTrue(response.isSuccess()); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java new file mode 100644 index 000000000..5b95b6d3b --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java @@ -0,0 +1,20 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.substituteNode.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!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java new file mode 100644 index 000000000..495db7ac3 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java @@ -0,0 +1,21 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.substituteNode.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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java new file mode 100644 index 000000000..dca6da62a --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java @@ -0,0 +1,21 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.substituteNode.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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java new file mode 100644 index 000000000..620490341 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java @@ -0,0 +1,21 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.substituteNode.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("sub") +public class SubCmp extends NodeComponent { + + @Override + public void process() { + System.out.println("SubCmp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/application.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/application.properties new file mode 100644 index 000000000..35bdc3a1e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/application.properties @@ -0,0 +1,2 @@ +liteflow.rule-source=substituteNode/flow.el.xml +liteflow.substitute-cmp-class=com.yomahub.liteflow.test.substituteNode.cmp.SubCmp \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/flow.el.xml new file mode 100644 index 000000000..2ac202b9b --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/flow.el.xml @@ -0,0 +1,10 @@ + + + + THEN(node("a"), node("b"), node("c")); + + + + THEN(node("a"), node("b"), node("93-nodeTEST")); + + \ No newline at end of file