Переглянути джерело

feature #I5IA5U 提供节点包装语法+替补节点的功能,增加el表达式来完成

everywhere.z 2 роки тому
батько
коміт
daa65d0d0e
14 змінених файлів з 236 додано та 0 видалено
  1. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java
  2. 65 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java
  3. 11 0
      liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java
  4. 11 0
      liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java
  5. 1 0
      liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowPropertyAutoConfiguration.java
  6. 7 0
      liteflow-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
  7. 1 0
      liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties
  8. 44 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java
  9. 20 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java
  10. 21 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java
  11. 21 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java
  12. 21 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java
  13. 2 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/application.properties
  14. 10 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/flow.el.xml

+ 1 - 0
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

+ 65 - 0
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();
+            }
+        }
+    }
+}

+ 11 - 0
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;
+    }
 }

+ 11 - 0
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;
+    }
 }

+ 1 - 0
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;
     }
 }

+ 7 - 0
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",

+ 1 - 0
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

+ 44 - 0
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());
+    }
+}

+ 20 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java

@@ -0,0 +1,20 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @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!");
+	}
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @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!");
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @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!");
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @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!");
+	}
+
+}

+ 2 - 0
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

+ 10 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/flow.el.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<flow>
+    <chain name="chain1">
+        THEN(node("a"), node("b"), node("c"));
+    </chain>
+
+    <chain name="chain2">
+        THEN(node("a"), node("b"), node("93-nodeTEST"));
+    </chain>
+</flow>