浏览代码

Merge branch 'dev'

# Conflicts:
#	README.zh-CN.md
everywhere.z 2 年之前
父节点
当前提交
1d5102b5d8
共有 100 个文件被更改,包括 2510 次插入1071 次删除
  1. 1 1
      README.md
  2. 3 3
      README.zh-CN.md
  3. 10 2
      liteflow-core/pom.xml
  4. 1 1
      liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowSwitchCmpDefine.java
  5. 3 3
      liteflow-core/src/main/java/com/yomahub/liteflow/aop/ICmpAroundAspect.java
  6. 49 27
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowChainBuilder.java
  7. 38 32
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowConditionBuilder.java
  8. 39 39
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java
  9. 3 2
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowWhenConditionBuilder.java
  10. 156 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java
  11. 55 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/AnyOperator.java
  12. 42 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/FinallyOperator.java
  13. 55 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IdOperator.java
  14. 56 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IgnoreErrorOperator.java
  15. 42 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/PreOperator.java
  16. 49 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java
  17. 61 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/TagOperator.java
  18. 41 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ThenOperator.java
  19. 55 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ThreadPoolOperator.java
  20. 54 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ToOperator.java
  21. 40 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/WhenOperator.java
  22. 93 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/prop/ChainPropBean.java
  23. 91 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/prop/NodePropBean.java
  24. 39 0
      liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java
  25. 3 1
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ComponentInitializer.java
  26. 149 99
      liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java
  27. 36 35
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java
  28. 4 4
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeSwitchComponent.java
  29. 1 1
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptComponent.java
  30. 2 2
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptSwitchComponent.java
  31. 2 0
      liteflow-core/src/main/java/com/yomahub/liteflow/enums/ConditionTypeEnum.java
  32. 1 1
      liteflow-core/src/main/java/com/yomahub/liteflow/enums/ExecuteTypeEnum.java
  33. 7 4
      liteflow-core/src/main/java/com/yomahub/liteflow/enums/FlowParserTypeEnum.java
  34. 1 1
      liteflow-core/src/main/java/com/yomahub/liteflow/enums/LiteFlowMethodEnum.java
  35. 3 1
      liteflow-core/src/main/java/com/yomahub/liteflow/enums/NodeTypeEnum.java
  36. 30 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ChainDuplicateException.java
  37. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ChainEndException.java
  38. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ChainNotFoundException.java
  39. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ComponentCannotRegisterException.java
  40. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ComponentMethodDefineErrorException.java
  41. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ComponentNotAccessException.java
  42. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ComponentProxyErrorException.java
  43. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ConfigErrorException.java
  44. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/CyclicDependencyException.java
  45. 25 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ELParseException.java
  46. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/EmptyConditionValueException.java
  47. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ErrorSupportPathException.java
  48. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ExecutableItemNotFoundException.java
  49. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/FlowExecutorNotInitException.java
  50. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/FlowSystemException.java
  51. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/MultipleParsersException.java
  52. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/NoAvailableSlotException.java
  53. 30 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/NoSuchContextBeanException.java
  54. 25 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/NoSwitchTargetNodeException.java
  55. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/NodeBuildException.java
  56. 25 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/NodeClassNotFoundException.java
  57. 25 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/NodeTypeCanNotGuessException.java
  58. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/NodeTypeNotSupportException.java
  59. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/NotSupportConditionException.java
  60. 25 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/NullNodeTypeException.java
  61. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ParseException.java
  62. 22 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ParserCannotFindException.java
  63. 30 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/RequestIdGeneratorException.java
  64. 25 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/SwitchTargetCannotBePreOrFinallyException.java
  65. 25 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/SwitchTypeErrorException.java
  66. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ThreadExecutorServiceCreateException.java
  67. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/WhenExecuteException.java
  68. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/WhenTimeoutException.java
  69. 53 13
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java
  70. 21 13
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/LiteflowResponse.java
  71. 0 21
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/condition/FinallyCondition.java
  72. 0 21
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/condition/PreCondition.java
  73. 0 20
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/condition/ThenCondition.java
  74. 0 25
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/condition/WhenCondition.java
  75. 43 151
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java
  76. 6 20
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java
  77. 33 20
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/Condition.java
  78. 31 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/FinallyCondition.java
  79. 31 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/PreCondition.java
  80. 72 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/SwitchCondition.java
  81. 33 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ThenCondition.java
  82. 157 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java
  83. 1 1
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/executor/NodeExecutor.java
  84. 16 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/id/DefaultRequestIdGenerator.java
  85. 59 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/id/IdGeneratorHelper.java
  86. 17 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/id/RequestIdGenerator.java
  87. 0 6
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/CompletableFutureTimeout.java
  88. 3 2
      liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java
  89. 20 159
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/JsonFlowParser.java
  90. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/LocalXmlFlowParser.java
  91. 12 150
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java
  92. 8 33
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/YmlFlowParser.java
  93. 8 48
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperJsonFlowParser.java
  94. 7 51
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperXmlFlowParser.java
  95. 12 58
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperYmlFlowParser.java
  96. 49 0
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseJsonFlowParser.java
  97. 50 0
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseXmlFlowParser.java
  98. 57 0
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseYmlFlowParser.java
  99. 58 0
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseZookeeperJsonFlowParser.java
  100. 58 0
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseZookeeperXmlFlowParser.java

+ 1 - 1
README.md

@@ -10,7 +10,7 @@
 liteFlow is a lightweight , fast component-based process engine framework / rules engine , component orchestration , component reuse , to help decouple business code , so that each business fragment is an elegant component , and support hot-loading rule configuration , to achieve on-the-fly modification .
 
 ## Website url: [https://liteflow.yomahub.com](https://liteflow.yomahub.com/)
-## Documents url: [https://liteflow.yomahub.com/docs](https://liteflow.yomahub.com/docs)
+## Documents url: [https://liteflow.yomahub.com/pages/967466/](https://liteflow.yomahub.com/pages/967466/)
 ## Example projects: [https://gitee.com/bryan31/liteflow-example](https://gitee.com/bryan31/liteflow-example)
 
 ## Feature

+ 3 - 3
README.zh-CN.md

@@ -9,9 +9,9 @@
 ## 概述
 liteFlow是一个轻量,快速的组件式流程引擎框架/规则引擎,组件编排,组件复用,帮助解耦业务代码,让每一个业务片段都是一个优雅的组件,并支持热加载规则配置,实现即时修改。
 
-## 官网链接:[点这里进入官网](https://liteflow.yomahub.com/)
-## 文档链接:[点这里进入文档进行学习](https://liteflow.yomahub.com/pages/967466/)
-## 示例工程:[点这里进入示例工程项目](https://gitee.com/bryan31/liteflow-example)
+## 官网链接:[https://liteflow.yomahub.com](https://liteflow.yomahub.com/)
+## 文档链接:[https://liteflow.yomahub.com/pages/967466/](https://liteflow.yomahub.com/pages/967466/)
+## 示例工程:[https://gitee.com/bryan31/liteflow-example](https://gitee.com/bryan31/liteflow-example)
 
 ## 特性
 * **组件定义统一:** 所有的逻辑都是组件,为所有的逻辑提供统一化的组件实现方式,小身材,大能量。

+ 10 - 2
liteflow-core/pom.xml

@@ -9,7 +9,7 @@
     <parent>
 		<groupId>com.yomahub</groupId>
 		<artifactId>liteflow</artifactId>
-		<version>2.7.3</version>
+		<version>2.8.0</version>
 	</parent>
 
 	<dependencies>
@@ -36,7 +36,7 @@
 			<artifactId>snakeyaml</artifactId>
 		</dependency>
 		<dependency>
-			<groupId>dom4j</groupId>
+			<groupId>org.dom4j</groupId>
 			<artifactId>dom4j</artifactId>
 		</dependency>
 		<dependency>
@@ -51,6 +51,10 @@
 					<artifactId>slf4j-api</artifactId>
 					<groupId>org.slf4j</groupId>
 				</exclusion>
+				<exclusion>
+					<artifactId>commons-lang</artifactId>
+					<groupId>commons-lang</groupId>
+				</exclusion>
 			</exclusions>
 		</dependency>
 		<dependency>
@@ -65,5 +69,9 @@
 			<groupId>net.bytebuddy</groupId>
 			<artifactId>byte-buddy</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>QLExpress</artifactId>
+		</dependency>
 	</dependencies>
 </project>

+ 1 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowCondCmpDefine.java → liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowSwitchCmpDefine.java

@@ -6,5 +6,5 @@ import java.lang.annotation.*;
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 @Inherited
-public @interface LiteflowCondCmpDefine {
+public @interface LiteflowSwitchCmpDefine {
 }

+ 3 - 3
liteflow-core/src/main/java/com/yomahub/liteflow/aop/ICmpAroundAspect.java

@@ -14,9 +14,9 @@ import com.yomahub.liteflow.slot.Slot;
  * 实现这个接口并注入到spring上下文即可
  * @author Bryan.Zhang
  */
-public interface ICmpAroundAspect<T> {
+public interface ICmpAroundAspect {
 
-    void beforeProcess(String nodeId, Slot<T> slot);
+    void beforeProcess(String nodeId, Slot slot);
 
-    void afterProcess(String nodeId, Slot<T> slot);
+    void afterProcess(String nodeId, Slot slot);
 }

+ 49 - 27
liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowChainBuilder.java

@@ -1,16 +1,22 @@
 package com.yomahub.liteflow.builder;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
+import com.google.common.collect.Lists;
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
 import com.yomahub.liteflow.flow.FlowBus;
-import com.yomahub.liteflow.flow.condition.*;
 import com.yomahub.liteflow.flow.element.Chain;
+import com.yomahub.liteflow.flow.element.condition.Condition;
+import com.yomahub.liteflow.flow.element.condition.ThenCondition;
+import com.yomahub.liteflow.flow.element.condition.WhenCondition;
 
 import java.util.ArrayList;
 import java.util.List;
 
 /**
  * Chain基于代码形式的组装器
+ *
  * @author Bryan.Zhang
  * @since 2.6.8
  */
@@ -18,77 +24,93 @@ public class LiteFlowChainBuilder {
 
     private Chain chain;
 
+    //这是主体的Condition,不包含前置和后置
     //声明这个变量,而不是用chain.getConditionList的目的,是为了辅助平滑加载
     //虽然FlowBus里面的map都是CopyOnWrite类型的,但是在buildCondition的时候,为了平滑加载,所以不能事先把chain.getConditionList给设为空List
     //所以在这里做一个缓存,等conditionList全部build完毕后,再去一次性替换chain里面的conditionList
     private final List<Condition> conditionList;
 
-    public static LiteFlowChainBuilder createChain(){
+    //前置处理Condition,用来区别主体的Condition
+    private final List<Condition> preConditionList;
+
+    //后置处理Condition,用来区别主体的Condition
+    private final List<Condition> finallyConditionList;
+
+    public static LiteFlowChainBuilder createChain() {
         return new LiteFlowChainBuilder();
     }
 
-    public LiteFlowChainBuilder(){
+    public LiteFlowChainBuilder() {
         chain = new Chain();
         conditionList = new ArrayList<>();
+        preConditionList = new ArrayList<>();
+        finallyConditionList = new ArrayList<>();
     }
 
     //在parser中chain的build是2段式的,因为涉及到依赖问题,以前是递归parser
     //2.6.8之后取消了递归的模式,两段式组装,先把带有chainName的chain对象放进去,第二段再组装chain里面的condition
     //所以这里setChainName的时候需要判断下
-    public LiteFlowChainBuilder setChainName(String chainName){
-        if (FlowBus.containChain(chainName)){
+    public LiteFlowChainBuilder setChainName(String chainName) {
+        if (FlowBus.containChain(chainName)) {
             this.chain = FlowBus.getChain(chainName);
-        }else{
+        } else {
             this.chain.setChainName(chainName);
         }
         return this;
     }
 
-    public LiteFlowChainBuilder setCondition(Condition condition){
+    public LiteFlowChainBuilder setCondition(Condition condition) {
         //这里把condition组装进conditionList,
         buildConditions(condition);
         return this;
     }
 
-    public void build(){
+    public void build() {
         this.chain.setConditionList(this.conditionList);
+        this.chain.setPreConditionList(this.preConditionList);
+        this.chain.setFinallyConditionList(this.finallyConditionList);
+
+        checkBuild();
+
         FlowBus.addChain(this.chain);
     }
 
+    /**
+     * build 前简单校验
+     */
+    private void checkBuild() {
+        List<String> errorList = Lists.newArrayList();
+        if (StrUtil.isBlank(this.chain.getChainName())) {
+            errorList.add("name is blank");
+        }
+        if (CollUtil.isNotEmpty(errorList)) {
+            throw new RuntimeException(CollUtil.join(errorList, ",", "[", "]"));
+        }
+    }
+
     private void buildConditions(Condition condition) {
         //这里进行合并逻辑
         //对于then来说,相邻的2个then会合并成一个condition
         //对于when来说,相同组的when会合并成一个condition,不同组的when还是会拆开
         if (condition.getConditionType().equals(ConditionTypeEnum.TYPE_PRE)) {
-            this.conditionList.add(new PreCondition(condition));
+            this.preConditionList.add(condition);
+        } else if (condition.getConditionType().equals(ConditionTypeEnum.TYPE_FINALLY)) {
+            this.finallyConditionList.add(condition);
         } else if (condition.getConditionType().equals(ConditionTypeEnum.TYPE_THEN)) {
             if (this.conditionList.size() >= 1 &&
                     CollectionUtil.getLast(this.conditionList) instanceof ThenCondition) {
-                CollectionUtil.getLast(this.conditionList).getNodeList().addAll(condition.getNodeList());
+                CollectionUtil.getLast(this.conditionList).getExecutableList().addAll(condition.getExecutableList());
             } else {
-                this.conditionList.add(new ThenCondition(condition));
+                this.conditionList.add(condition);
             }
         } else if (condition.getConditionType().equals(ConditionTypeEnum.TYPE_WHEN)) {
-            if (this.conditionList.size() > 1 &&
+            if (this.conditionList.size() >= 1 &&
                     CollectionUtil.getLast(this.conditionList) instanceof WhenCondition &&
                     CollectionUtil.getLast(this.conditionList).getGroup().equals(condition.getGroup())) {
-                CollectionUtil.getLast(this.conditionList).getNodeList().addAll(condition.getNodeList());
+                CollectionUtil.getLast(this.conditionList).getExecutableList().addAll(condition.getExecutableList());
             } else {
-                this.conditionList.add(new WhenCondition(condition));
+                this.conditionList.add(condition);
             }
-        } else if (condition.getConditionType().equals(ConditionTypeEnum.TYPE_FINALLY)) {
-            this.conditionList.add(new FinallyCondition(condition));
         }
-
-        //每一次build之后,对conditionList进行排序,pre最前面,finally最后
-        //这里为什么要排序,因为在声明的时候,哪怕有人不把pre放最前,finally放最后,但最终也要确保是正确的顺序
-        CollectionUtil.sort(this.conditionList, (o1, o2) -> {
-            if (o1.getConditionType().equals(ConditionTypeEnum.TYPE_PRE) || o2.getConditionType().equals(ConditionTypeEnum.TYPE_FINALLY)){
-                return -1;
-            } else if (o2.getConditionType().equals(ConditionTypeEnum.TYPE_PRE) || o1.getConditionType().equals(ConditionTypeEnum.TYPE_FINALLY)){
-                return 1;
-            }
-            return 0;
-        });
     }
 }

+ 38 - 32
liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowConditionBuilder.java

@@ -5,7 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.core.NodeComponent;
 import com.yomahub.liteflow.flow.element.Chain;
-import com.yomahub.liteflow.flow.condition.Condition;
+import com.yomahub.liteflow.flow.element.condition.*;
 import com.yomahub.liteflow.builder.entity.ExecutableEntity;
 import com.yomahub.liteflow.flow.element.Node;
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
@@ -15,7 +15,6 @@ import com.yomahub.liteflow.parser.RegexEntity;
 import com.yomahub.liteflow.parser.RegexNodeEntity;
 import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -28,29 +27,38 @@ public class LiteFlowConditionBuilder {
     protected Condition condition;
 
     public static LiteFlowConditionBuilder createCondition(ConditionTypeEnum conditionType){
-        return new LiteFlowConditionBuilder(conditionType);
+        switch (conditionType){
+            case TYPE_THEN:
+                return createThenCondition();
+            case TYPE_WHEN:
+                return createWhenCondition();
+            case TYPE_PRE:
+                return createPreCondition();
+            case TYPE_FINALLY:
+                return createFinallyCondition();
+            default:
+                return null;
+        }
     }
 
     public static LiteFlowConditionBuilder createThenCondition(){
-        return new LiteFlowConditionBuilder(ConditionTypeEnum.TYPE_THEN);
+        return new LiteFlowConditionBuilder(new ThenCondition());
     }
 
     public static LiteFlowWhenConditionBuilder createWhenCondition(){
-        return new LiteFlowWhenConditionBuilder(ConditionTypeEnum.TYPE_WHEN);
+        return new LiteFlowWhenConditionBuilder(new WhenCondition());
     }
 
     public static LiteFlowConditionBuilder createPreCondition(){
-        return new LiteFlowConditionBuilder(ConditionTypeEnum.TYPE_PRE);
+        return new LiteFlowConditionBuilder(new PreCondition());
     }
 
     public static LiteFlowConditionBuilder createFinallyCondition(){
-        return new LiteFlowConditionBuilder(ConditionTypeEnum.TYPE_FINALLY);
+        return new LiteFlowConditionBuilder(new FinallyCondition());
     }
 
-    public LiteFlowConditionBuilder(ConditionTypeEnum conditionType){
-        this.condition = new Condition();
-        this.condition.setConditionType(conditionType);
-        this.condition.setNodeList(new ArrayList<>());
+    public LiteFlowConditionBuilder(Condition condition){
+        this.condition = condition;
     }
 
     public LiteFlowConditionBuilder setValue(String value){
@@ -84,32 +92,25 @@ public class LiteFlowConditionBuilder {
         return executableEntity;
     }
 
-    // 设置执行节点或流程列表
-    public LiteFlowConditionBuilder setExecutables(List<ExecutableEntity> executableEntities) {
-        if (CollUtil.isEmpty(executableEntities)) {
-            return this;
-        }
-        for (ExecutableEntity conditionNodeEntity : executableEntities) {
-            setExecutable(conditionNodeEntity);
-        }
-        return this;
-    }
-
     // 设置执行节点或者流程
     public LiteFlowConditionBuilder setExecutable(ExecutableEntity executableEntity) {
         if (FlowBus.containNode(executableEntity.getId())) {
             Node node = FlowBus.copyNode(executableEntity.getId());
             node.setTag(executableEntity.getTag());
-            this.condition.getNodeList().add(node);
-            // 构建条件节点-通过是否包含条件节点列表-解析条件节点会含有realItem,也就是括号里的node
-            buildCondNode(node, executableEntity.getNodeCondComponents());
+
+            //如果没有条件节点,说明是普通组件,如果有条件节点,就去构建SwitchCondition
+            if (CollUtil.isEmpty(executableEntity.getNodeCondComponents())) {
+                this.condition.getExecutableList().add(node);
+            }else{
+                buildSwitchNode(node, executableEntity.getNodeCondComponents());
+            }
         } else if (hasChain(executableEntity.getId())) {
             Chain chain = FlowBus.getChain(executableEntity.getId());
-            this.condition.getNodeList().add(chain);
+            this.condition.getExecutableList().add(chain);
         } else {
             //元数据没有的话,从spring上下文再取一遍
             //这部分有2个目的
-            //一是为了防止标有@Lazy懒加载的组件,二是spring负责扫描,而用代码的形式加载chain这种情况。
+            //一是为了防止标有@Lazy懒加载的组件,二是spring负责扫描,而用动态代码的形式加载组件这种情况。
             NodeComponent nodeComponent =  ContextAwareHolder.loadContextAware().getBean(executableEntity.getId());
             if (ObjectUtil.isNotNull(nodeComponent)){
                 FlowBus.addSpringScanNode(executableEntity.getId(), nodeComponent);
@@ -123,23 +124,28 @@ public class LiteFlowConditionBuilder {
     }
 
     // 构建条件节点
-    private void buildCondNode(Node node, List<ExecutableEntity> executableEntities) {
+    private void buildSwitchNode(Node node, List<ExecutableEntity> executableEntities) {
         if (CollUtil.isEmpty(executableEntities)) {
             return;
         }
+
+        SwitchCondition switchCondition = new SwitchCondition();
+        switchCondition.setSwitchNode(node);
+
         for (ExecutableEntity realItem : executableEntities) {
             if (FlowBus.containNode(realItem.getId())) {
-                Node condNode = FlowBus.copyNode(realItem.getId());
-                condNode.setTag(realItem.getTag());
-                node.setCondNode(condNode.getId(), condNode);
+                Node targetNode = FlowBus.copyNode(realItem.getId());
+                targetNode.setTag(realItem.getTag());
+                switchCondition.addTargetItem(targetNode);
             } else if (hasChain(realItem.getId())) {
                 Chain chain = FlowBus.getChain(realItem.getId());
-                node.setCondNode(chain.getChainName(), chain);
+                switchCondition.addTargetItem(chain);
             } else{
                 String errorMsg = StrUtil.format("executable node[{}] is not found!", realItem.getId());
                 throw new ExecutableItemNotFoundException(errorMsg);
             }
         }
+        this.condition.getExecutableList().add(switchCondition);
     }
 
     public Condition build(){

+ 39 - 39
liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java

@@ -1,18 +1,19 @@
 package com.yomahub.liteflow.builder;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.io.resource.ResourceUtil;
-import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
-import com.yomahub.liteflow.core.NodeComponent;
-import com.yomahub.liteflow.flow.element.Node;
+import com.google.common.collect.Lists;
 import com.yomahub.liteflow.enums.NodeTypeEnum;
 import com.yomahub.liteflow.exception.NodeBuildException;
-import com.yomahub.liteflow.exception.NullParamException;
 import com.yomahub.liteflow.flow.FlowBus;
-import org.apache.commons.lang.StringUtils;
+import com.yomahub.liteflow.flow.element.Node;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.List;
+import java.util.Objects;
+
 public class LiteFlowNodeBuilder {
 
     private final Logger LOG = LoggerFactory.getLogger(this.getClass());
@@ -23,20 +24,20 @@ public class LiteFlowNodeBuilder {
         return new LiteFlowNodeBuilder();
     }
 
-    public static LiteFlowNodeBuilder createCommonNode(){
+    public static LiteFlowNodeBuilder createCommonNode() {
         return new LiteFlowNodeBuilder(NodeTypeEnum.COMMON);
     }
 
-    public static LiteFlowNodeBuilder createCommonCondNode(){
-        return new LiteFlowNodeBuilder(NodeTypeEnum.COMMON);
+    public static LiteFlowNodeBuilder createCommonCondNode() {
+        return new LiteFlowNodeBuilder(NodeTypeEnum.SWITCH);
     }
 
-    public static LiteFlowNodeBuilder createScriptNode(){
+    public static LiteFlowNodeBuilder createScriptNode() {
         return new LiteFlowNodeBuilder(NodeTypeEnum.SCRIPT);
     }
 
-    public static LiteFlowNodeBuilder createScriptCondNode(){
-        return new LiteFlowNodeBuilder(NodeTypeEnum.COND_SCRIPT);
+    public static LiteFlowNodeBuilder createScriptSwitchNode() {
+        return new LiteFlowNodeBuilder(NodeTypeEnum.SWITCH_SCRIPT);
     }
 
     public LiteFlowNodeBuilder() {
@@ -49,7 +50,7 @@ public class LiteFlowNodeBuilder {
     }
 
     public LiteFlowNodeBuilder setId(String nodeId) {
-        if (StrUtil.isBlank(nodeId)){
+        if (StrUtil.isBlank(nodeId)) {
             return this;
         }
         this.node.setId(nodeId.trim());
@@ -57,7 +58,7 @@ public class LiteFlowNodeBuilder {
     }
 
     public LiteFlowNodeBuilder setName(String name) {
-        if (StrUtil.isBlank(name)){
+        if (StrUtil.isBlank(name)) {
             return this;
         }
         this.node.setName(name.trim());
@@ -65,51 +66,31 @@ public class LiteFlowNodeBuilder {
     }
 
     public LiteFlowNodeBuilder setClazz(String clazz) {
-        if (StrUtil.isBlank(clazz)){
+        if (StrUtil.isBlank(clazz)) {
             return this;
         }
         this.node.setClazz(clazz.trim());
         return this;
     }
 
-    public LiteFlowNodeBuilder setClazz(Class<?> clazz){
+    public LiteFlowNodeBuilder setClazz(Class<?> clazz) {
         assert clazz != null;
         setClazz(clazz.getName());
         return this;
     }
 
-    // 设置节点组件的class
-    public LiteFlowNodeBuilder setNodeComponentClazz(Class<? extends NodeComponent> nodeComponentClass) {
-        assert nodeComponentClass != null;
-        setClazz(nodeComponentClass.getName());
-        return this;
-    }
-
     public LiteFlowNodeBuilder setType(NodeTypeEnum type) {
         this.node.setType(type);
         return this;
     }
 
-    // 设置类型的编码
-    public LiteFlowNodeBuilder setTypeCode(String nodeTypeCode) {
-       if (StringUtils.isBlank(nodeTypeCode)) {
-            throw new NullParamException("nodeTypeCode is blank");
-        }
-        NodeTypeEnum nodeTypeEnum = NodeTypeEnum.getEnumByCode(nodeTypeCode);
-        if (ObjectUtil.isNull(nodeTypeEnum)) {
-            throw new NullParamException(StrUtil.format("nodeTypeCode[{}] is error", nodeTypeCode));
-        }
-        setType(nodeTypeEnum);
-        return this;
-    }
-
     public LiteFlowNodeBuilder setScript(String script) {
         this.node.setScript(script);
         return this;
     }
 
     public LiteFlowNodeBuilder setFile(String filePath) {
-        if (StrUtil.isBlank(filePath)){
+        if (StrUtil.isBlank(filePath)) {
             return this;
         }
         String script = ResourceUtil.readUtf8Str(StrUtil.format("classpath: {}", filePath.trim()));
@@ -117,13 +98,16 @@ public class LiteFlowNodeBuilder {
     }
 
     public void build() {
+        checkBuild();
         try {
             if (this.node.getType().equals(NodeTypeEnum.COMMON)) {
                 FlowBus.addCommonNode(this.node.getId(), this.node.getName(), this.node.getClazz());
-            } else if (this.node.getType().equals(NodeTypeEnum.SCRIPT)){
+            } else if (this.node.getType().equals(NodeTypeEnum.SWITCH)) {
+                FlowBus.addSwitchNode(this.node.getId(), this.node.getName(), this.node.getClazz());
+            } else if (this.node.getType().equals(NodeTypeEnum.SCRIPT)) {
                 FlowBus.addCommonScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
-            } else if (this.node.getType().equals(NodeTypeEnum.COND_SCRIPT)){
-                FlowBus.addCondScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
+            } else if (this.node.getType().equals(NodeTypeEnum.SWITCH_SCRIPT)) {
+                FlowBus.addSwitchScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
             }
         } catch (Exception e) {
             String errMsg = StrUtil.format("An exception occurred while building the node[{}]", this.node.getId());
@@ -131,4 +115,20 @@ public class LiteFlowNodeBuilder {
             throw new NodeBuildException(errMsg);
         }
     }
+
+    /**
+     * build 前简单校验
+     */
+    private void checkBuild() {
+        List<String> errorList = Lists.newArrayList();
+        if (StrUtil.isBlank(this.node.getId())) {
+            errorList.add("id is blank");
+        }
+        if (Objects.isNull(this.node.getType())) {
+            errorList.add("type is null");
+        }
+        if (CollUtil.isNotEmpty(errorList)) {
+            throw new NodeBuildException(CollUtil.join(errorList, ",", "[", "]"));
+        }
+    }
 }

+ 3 - 2
liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowWhenConditionBuilder.java

@@ -3,6 +3,7 @@ package com.yomahub.liteflow.builder;
 import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.common.LocalDefaultFlowConstant;
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.flow.element.condition.Condition;
 
 /**
  * WhenCondition基于代码形式的组装器
@@ -12,8 +13,8 @@ import com.yomahub.liteflow.enums.ConditionTypeEnum;
  */
 public class LiteFlowWhenConditionBuilder extends LiteFlowConditionBuilder{
 
-    public LiteFlowWhenConditionBuilder(ConditionTypeEnum conditionType) {
-        super(conditionType);
+    public LiteFlowWhenConditionBuilder(Condition condition) {
+        super(condition);
     }
 
     public LiteFlowWhenConditionBuilder setErrorResume(boolean errorResume){

+ 156 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java

@@ -0,0 +1,156 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
+import com.google.common.collect.Lists;
+import com.ql.util.express.DefaultContext;
+import com.ql.util.express.ExpressRunner;
+import com.yomahub.liteflow.builder.el.operator.*;
+import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.exception.ELParseException;
+import com.yomahub.liteflow.exception.FlowSystemException;
+import com.yomahub.liteflow.flow.FlowBus;
+import com.yomahub.liteflow.flow.element.Chain;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.condition.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+/**
+ * Chain基于代码形式的组装器
+ * EL表达式规则专属组装器
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class LiteFlowChainELBuilder {
+
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    private Chain chain;
+
+    //这是主体的Condition,不包含前置和后置
+    //声明这个变量,而不是用chain.getConditionList的目的,是为了辅助平滑加载
+    //虽然FlowBus里面的map都是CopyOnWrite类型的,但是在buildCondition的时候,为了平滑加载,所以不能事先把chain.getConditionList给设为空List
+    //所以在这里做一个缓存,等conditionList全部build完毕后,再去一次性替换chain里面的conditionList
+    private final List<Condition> conditionList;
+
+    //前置处理Condition,用来区别主体的Condition
+    private final List<Condition> preConditionList;
+
+    //后置处理Condition,用来区别主体的Condition
+    private final List<Condition> finallyConditionList;
+
+    //EL解析引擎
+    private final ExpressRunner expressRunner;
+
+    public static LiteFlowChainELBuilder createChain() {
+        return new LiteFlowChainELBuilder();
+    }
+
+    public LiteFlowChainELBuilder() {
+        chain = new Chain();
+        conditionList = new ArrayList<>();
+        preConditionList = new ArrayList<>();
+        finallyConditionList = new ArrayList<>();
+
+        //初始化QLExpress的Runner
+        expressRunner = new ExpressRunner();
+        expressRunner.addFunction("THEN", new ThenOperator());
+        expressRunner.addFunction("WHEN", new WhenOperator());
+        expressRunner.addFunction("SWITCH", new SwitchOperator());
+        expressRunner.addFunction("PRE", new PreOperator());
+        expressRunner.addFunction("FINALLY", new FinallyOperator());
+        expressRunner.addFunctionAndClassMethod("to", Object.class, new ToOperator());
+        expressRunner.addFunctionAndClassMethod("tag", Object.class, new TagOperator());
+        expressRunner.addFunctionAndClassMethod("any", Object.class, new AnyOperator());
+        expressRunner.addFunctionAndClassMethod("id", Object.class, new IdOperator());
+        expressRunner.addFunctionAndClassMethod("ignoreError", Object.class, new IgnoreErrorOperator());
+        expressRunner.addFunctionAndClassMethod("threadPool", Object.class, new ThreadPoolOperator());
+    }
+
+    //在parser中chain的build是2段式的,因为涉及到依赖问题,以前是递归parser
+    //2.6.8之后取消了递归的模式,两段式组装,先把带有chainName的chain对象放进去,第二段再组装chain里面的condition
+    //所以这里setChainName的时候需要判断下
+    public LiteFlowChainELBuilder setChainName(String chainName) {
+        if (FlowBus.containChain(chainName)) {
+            this.chain = FlowBus.getChain(chainName);
+        } else {
+            this.chain.setChainName(chainName);
+        }
+        return this;
+    }
+
+    public LiteFlowChainELBuilder setEL(String elStr) {
+        if (StrUtil.isBlank(elStr)){
+            String errMsg = StrUtil.format("no conditionList in this chain[{}]", chain.getChainName());
+            throw new FlowSystemException(errMsg);
+        }
+
+        List<String> errorList = new ArrayList<>();
+        try{
+            DefaultContext<String, Object> context = new DefaultContext<>();
+
+            //这里一定要先放chain,再放node,因为node优先于chain,所以当重名时,node会覆盖掉chain
+            //往上下文里放入所有的chain,是的el表达式可以直接引用到chain
+            FlowBus.getChainMap().values().forEach(chain -> context.put(chain.getChainName(), chain));
+
+            //往上下文里放入所有的node,使得el表达式可以直接引用到nodeId
+            FlowBus.getNodeMap().keySet().forEach(nodeId -> context.put(nodeId, FlowBus.getNode(nodeId)));
+
+            //解析el成为一个Condition
+            //为什么这里只是一个Condition,而不是一个List<Condition>呢
+            //这里无论多复杂的,外面必定有一个最外层的Condition,所以这里只有一个,内部可以嵌套很多层,这点和以前的不太一样
+            Condition condition = (Condition) expressRunner.execute(elStr, context, errorList, false, true);
+
+            //从condition的第一层嵌套结构里拿出Pre和Finally节点
+            //为什么只寻找第一层,而不往下寻找了呢?
+            //因为这是一个规范,如果在后面的层级中出现pre和finally,语义上也不好理解,所以pre和finally只能定义在第一层
+            //如果硬是要在后面定义,则执行的时候会忽略,相关代码已做了判断
+            for (Executable executable : condition.getExecutableList()){
+                if (executable instanceof PreCondition){
+                    this.preConditionList.add((PreCondition) executable);
+                } else if (executable instanceof FinallyCondition) {
+                    this.finallyConditionList.add((FinallyCondition) executable);
+                }
+            }
+
+            //把主要的condition加入
+            this.conditionList.add(condition);
+            return this;
+        }catch (Exception e){
+            for (String scriptErrorMsg : errorList){
+                LOG.error("\n{}", scriptErrorMsg);
+            }
+            throw new ELParseException(e.getMessage());
+        }
+    }
+
+    public void build() {
+        this.chain.setConditionList(this.conditionList);
+        this.chain.setPreConditionList(this.preConditionList);
+        this.chain.setFinallyConditionList(this.finallyConditionList);
+
+        checkBuild();
+
+        FlowBus.addChain(this.chain);
+    }
+
+    /**
+     * build 前简单校验
+     */
+    private void checkBuild() {
+        List<String> errorList = Lists.newArrayList();
+        if (StrUtil.isBlank(this.chain.getChainName())) {
+            errorList.add("name is blank");
+        }
+        if (CollUtil.isNotEmpty(errorList)) {
+            throw new RuntimeException(CollUtil.join(errorList, ",", "[", "]"));
+        }
+    }
+}

+ 55 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/AnyOperator.java

@@ -0,0 +1,55 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.ql.util.express.Operator;
+import com.yomahub.liteflow.exception.ELParseException;
+import com.yomahub.liteflow.flow.element.condition.WhenCondition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EL规则中的any的操作符
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class AnyOperator extends Operator {
+
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    @Override
+    public WhenCondition executeInner(Object[] objects) throws Exception {
+        try{
+            if (ArrayUtil.isEmpty(objects)){
+                throw new Exception();
+            }
+
+            if (objects.length != 2){
+                LOG.error("parameter error");
+                throw new Exception();
+            }
+
+            WhenCondition whenCondition;
+            if (objects[0] instanceof WhenCondition){
+                whenCondition = (WhenCondition) objects[0];
+            }else{
+                LOG.error("The caller must be when condition item!");
+                throw new Exception();
+            }
+
+            boolean any = false;
+            if (objects[1] instanceof Boolean){
+                any = Boolean.parseBoolean(objects[1].toString());
+            }else{
+                LOG.error("the parameter must be boolean type!");
+                throw new Exception();
+            }
+
+            whenCondition.setAny(any);
+
+            return whenCondition;
+
+        }catch (Exception e){
+            throw new ELParseException("errors occurred in EL parsing");
+        }
+    }
+}

+ 42 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/FinallyOperator.java

@@ -0,0 +1,42 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import com.ql.util.express.Operator;
+import com.yomahub.liteflow.exception.ELParseException;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.condition.FinallyCondition;
+import com.yomahub.liteflow.flow.element.condition.PreCondition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EL规则中的THEN的操作符
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class FinallyOperator extends Operator {
+
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    @Override
+    public Object executeInner(Object[] objects) throws Exception {
+        try{
+            if (objects.length <= 0){
+                LOG.error("parameter error");
+                throw new Exception();
+            }
+
+            FinallyCondition finallyCondition = new FinallyCondition();
+            for (Object obj : objects){
+                if (obj instanceof Executable){
+                    finallyCondition.addExecutable((Executable)obj);
+                }else{
+                    LOG.error("parameter must be executable item!");
+                    throw new Exception();
+                }
+            }
+            return finallyCondition;
+        }catch (Exception e){
+            throw new ELParseException("errors occurred in EL parsing");
+        }
+    }
+}

+ 55 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IdOperator.java

@@ -0,0 +1,55 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.ql.util.express.Operator;
+import com.yomahub.liteflow.exception.ELParseException;
+import com.yomahub.liteflow.flow.element.condition.Condition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EL规则中的id的操作符,只有condition可加id
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class IdOperator extends Operator {
+
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    @Override
+    public Condition executeInner(Object[] objects) throws Exception {
+        try{
+            if (ArrayUtil.isEmpty(objects)){
+                throw new Exception();
+            }
+
+            if (objects.length != 2){
+                LOG.error("parameter error");
+                throw new Exception();
+            }
+
+            Condition condition;
+            if (objects[0] instanceof Condition){
+                condition = (Condition) objects[0];
+            }else{
+                LOG.error("The caller must be condition item!");
+                throw new Exception();
+            }
+
+            String id;
+            if (objects[1] instanceof String){
+                id = objects[1].toString();
+            }else{
+                LOG.error("the parameter must be String type!");
+                throw new Exception();
+            }
+
+            condition.setId(id);
+
+            return condition;
+
+        }catch (Exception e){
+            throw new ELParseException("errors occurred in EL parsing");
+        }
+    }
+}

+ 56 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IgnoreErrorOperator.java

@@ -0,0 +1,56 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.ql.util.express.Operator;
+import com.yomahub.liteflow.exception.ELParseException;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.condition.Condition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EL规则中的ignoreError的操作符
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class IgnoreErrorOperator extends Operator {
+
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    @Override
+    public Condition executeInner(Object[] objects) throws Exception {
+        try{
+            if (ArrayUtil.isEmpty(objects)){
+                throw new Exception();
+            }
+
+            if (objects.length != 2){
+                LOG.error("parameter error");
+                throw new Exception();
+            }
+
+            Condition condition;
+            if (objects[0] instanceof Condition){
+                condition = (Condition) objects[0];
+            }else{
+                LOG.error("The caller must be executable item!");
+                throw new Exception();
+            }
+
+            boolean ignoreError = false;
+            if (objects[1] instanceof Boolean){
+                ignoreError = Boolean.parseBoolean(objects[1].toString());
+            }else{
+                LOG.error("the parameter must be boolean type!");
+                throw new Exception();
+            }
+
+            condition.setErrorResume(ignoreError);
+
+            return condition;
+
+        }catch (Exception e){
+            throw new ELParseException("errors occurred in EL parsing");
+        }
+    }
+}

+ 42 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/PreOperator.java

@@ -0,0 +1,42 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import com.ql.util.express.Operator;
+import com.yomahub.liteflow.exception.ELParseException;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.condition.PreCondition;
+import com.yomahub.liteflow.flow.element.condition.ThenCondition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EL规则中的THEN的操作符
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class PreOperator extends Operator {
+
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    @Override
+    public Object executeInner(Object[] objects) throws Exception {
+        try{
+            if (objects.length <= 0){
+                LOG.error("parameter error");
+                throw new Exception();
+            }
+
+            PreCondition preCondition = new PreCondition();
+            for (Object obj : objects){
+                if (obj instanceof Executable){
+                    preCondition.addExecutable((Executable)obj);
+                }else{
+                    LOG.error("parameter must be executable item!");
+                    throw new Exception();
+                }
+            }
+            return preCondition;
+        }catch (Exception e){
+            throw new ELParseException("errors occurred in EL parsing");
+        }
+    }
+}

+ 49 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java

@@ -0,0 +1,49 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.ql.util.express.Operator;
+import com.yomahub.liteflow.exception.ELParseException;
+import com.yomahub.liteflow.flow.element.Node;
+import com.yomahub.liteflow.flow.element.condition.SwitchCondition;
+import com.yomahub.liteflow.flow.element.condition.WhenCondition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EL规则中的SWITCH的操作符
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class SwitchOperator extends Operator {
+
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    @Override
+    public SwitchCondition executeInner(Object[] objects) throws Exception {
+        try{
+            if (ArrayUtil.isEmpty(objects)){
+                throw new Exception();
+            }
+
+            if (objects.length != 1){
+                LOG.error("parameter error");
+                throw new Exception();
+            }
+
+            Node switchNode;
+            if (objects[0] instanceof Node){
+                switchNode = (Node) objects[0];
+            }else{
+                LOG.error("The caller must be Node item!");
+                throw new Exception();
+            }
+
+            SwitchCondition switchCondition = new SwitchCondition();
+            switchCondition.setSwitchNode(switchNode);
+
+            return switchCondition;
+        }catch (Exception e){
+            throw new ELParseException("errors occurred in EL parsing");
+        }
+    }
+}

+ 61 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/TagOperator.java

@@ -0,0 +1,61 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.ql.util.express.Operator;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.exception.ELParseException;
+import com.yomahub.liteflow.flow.FlowBus;
+import com.yomahub.liteflow.flow.element.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EL规则中的tag的操作符
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class TagOperator extends Operator {
+
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    @Override
+    public Node executeInner(Object[] objects) throws Exception {
+        try{
+            if (ArrayUtil.isEmpty(objects)){
+                throw new Exception();
+            }
+
+            if (objects.length != 2){
+                LOG.error("parameter error");
+                throw new Exception();
+            }
+
+            Node node;
+            if (objects[0] instanceof Node){
+                node = (Node) objects[0];
+            }else{
+                LOG.error("The caller must be Node item!");
+                throw new Exception();
+            }
+
+            String tag = null;
+            if (objects[1] instanceof String){
+                tag = objects[1].toString();
+            }else{
+                LOG.error("the parameter must be String type!");
+                throw new Exception();
+            }
+
+            //这里为什么要clone一个呢?
+            //因为tag是跟着chain走的。而在el上下文里的放的都是同一个node,如果多个同样的node tag不同,则这里必须copy
+            Node copyNode = FlowBus.copyNode(node.getId());
+
+            copyNode.setTag(tag);
+
+            return copyNode;
+
+        }catch (Exception e){
+            throw new ELParseException("errors occurred in EL parsing");
+        }
+    }
+}

+ 41 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ThenOperator.java

@@ -0,0 +1,41 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import com.ql.util.express.Operator;
+import com.yomahub.liteflow.exception.ELParseException;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.condition.ThenCondition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EL规则中的THEN的操作符
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class ThenOperator extends Operator {
+
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    @Override
+    public Object executeInner(Object[] objects) throws Exception {
+        try{
+            if (objects.length <= 0){
+                LOG.error("parameter error");
+                throw new Exception();
+            }
+
+            ThenCondition thenCondition = new ThenCondition();
+            for (Object obj : objects){
+                if (obj instanceof Executable){
+                    thenCondition.addExecutable((Executable)obj);
+                }else{
+                    LOG.error("parameter must be executable item!");
+                    throw new Exception();
+                }
+            }
+            return thenCondition;
+        }catch (Exception e){
+            throw new ELParseException("errors occurred in EL parsing");
+        }
+    }
+}

+ 55 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ThreadPoolOperator.java

@@ -0,0 +1,55 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.ql.util.express.Operator;
+import com.yomahub.liteflow.exception.ELParseException;
+import com.yomahub.liteflow.flow.element.condition.WhenCondition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EL规则中的threadPool的操作符
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class ThreadPoolOperator extends Operator {
+
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    @Override
+    public WhenCondition executeInner(Object[] objects) throws Exception {
+        try{
+            if (ArrayUtil.isEmpty(objects)){
+                throw new Exception();
+            }
+
+            if (objects.length != 2){
+                LOG.error("parameter error");
+                throw new Exception();
+            }
+
+            WhenCondition whenCondition;
+            if (objects[0] instanceof WhenCondition){
+                whenCondition = (WhenCondition) objects[0];
+            }else{
+                LOG.error("The caller must be when condition item!");
+                throw new Exception();
+            }
+
+            String threadPoolClazz = null;
+            if (objects[1] instanceof String){
+                threadPoolClazz = objects[1].toString();
+            }else{
+                LOG.error("the parameter must be String type!");
+                throw new Exception();
+            }
+
+            whenCondition.setThreadExecutorClass(threadPoolClazz);
+
+            return whenCondition;
+
+        }catch (Exception e){
+            throw new ELParseException("errors occurred in EL parsing");
+        }
+    }
+}

+ 54 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ToOperator.java

@@ -0,0 +1,54 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.ql.util.express.Operator;
+import com.yomahub.liteflow.exception.ELParseException;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.condition.SwitchCondition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EL规则中的TO的操作符,用法须和SWITCH联合使用
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class ToOperator extends Operator {
+
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    @Override
+    public SwitchCondition executeInner(Object[] objects) throws Exception {
+        try{
+            if (ArrayUtil.isEmpty(objects)){
+                throw new Exception();
+            }
+
+            if (objects.length <= 2){
+                LOG.error("parameter error");
+                throw new Exception();
+            }
+
+            SwitchCondition switchCondition;
+            if (objects[0] instanceof SwitchCondition){
+                switchCondition = (SwitchCondition) objects[0];
+            }else{
+                LOG.error("The caller must be SwitchCondition item!");
+                throw new Exception();
+            }
+
+            for (int i = 1; i < objects.length; i++) {
+                if (objects[i] instanceof Executable) {
+                    Executable target = (Executable) objects[i];
+                    switchCondition.addTargetItem(target);
+                }else {
+                    LOG.error("The parameter must be Executable item!");
+                    throw new Exception();
+                }
+            }
+            return switchCondition;
+        }catch (Exception e){
+            throw new ELParseException("errors occurred in EL parsing");
+        }
+    }
+}

+ 40 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/WhenOperator.java

@@ -0,0 +1,40 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import com.ql.util.express.Operator;
+import com.yomahub.liteflow.exception.ELParseException;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.condition.WhenCondition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EL规则中的WHEN的操作符
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class WhenOperator extends Operator {
+
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    @Override
+    public WhenCondition executeInner(Object[] objects) throws Exception {
+        try{
+            if (objects.length <= 0){
+                LOG.error("parameter error");
+                throw new Exception();
+            }
+
+            WhenCondition whenCondition = new WhenCondition();
+            for (Object obj : objects){
+                if (obj instanceof Executable){
+                    whenCondition.addExecutable((Executable)obj);
+                }else{
+                    throw new Exception();
+                }
+            }
+            return whenCondition;
+        }catch (Exception e){
+            throw new ELParseException("errors occurred in EL parsing");
+        }
+    }
+}

+ 93 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/prop/ChainPropBean.java

@@ -0,0 +1,93 @@
+package com.yomahub.liteflow.builder.prop;
+
+import com.yomahub.liteflow.enums.ConditionTypeEnum;
+
+/**
+ * 构建 chain 的中间属性
+ */
+public class ChainPropBean {
+
+	/**
+	 * 执行规则
+	 */
+	String condValueStr;
+
+	/**
+	 * 分组
+	 */
+	String group;
+
+	/**
+	 * 是否抛出异常
+	 */
+	String errorResume;
+
+	/**
+	 * 满足任意条件,执行完成
+	 */
+	String any;
+
+	/**
+	 * 指定线程池
+	 */
+	String threadExecutorClass;
+
+	/**
+	 * chain 类型
+	 */
+	ConditionTypeEnum conditionType;
+
+	public String getCondValueStr() {
+		return condValueStr;
+	}
+
+	public ChainPropBean setCondValueStr(String condValueStr) {
+		this.condValueStr = condValueStr;
+		return this;
+	}
+
+	public String getGroup() {
+		return group;
+	}
+
+	public ChainPropBean setGroup(String group) {
+		this.group = group;
+		return this;
+	}
+
+	public String getErrorResume() {
+		return errorResume;
+	}
+
+	public ChainPropBean setErrorResume(String errorResume) {
+		this.errorResume = errorResume;
+		return this;
+	}
+
+	public String getAny() {
+		return any;
+	}
+
+	public ChainPropBean setAny(String any) {
+		this.any = any;
+		return this;
+	}
+
+	public String getThreadExecutorClass() {
+		return threadExecutorClass;
+	}
+
+	public ChainPropBean setThreadExecutorClass(String threadExecutorClass) {
+		this.threadExecutorClass = threadExecutorClass;
+		return this;
+	}
+
+	public ConditionTypeEnum getConditionType() {
+		return conditionType;
+	}
+
+	public ChainPropBean setConditionType(ConditionTypeEnum conditionType) {
+		this.conditionType = conditionType;
+		return this;
+	}
+}

+ 91 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/prop/NodePropBean.java

@@ -0,0 +1,91 @@
+package com.yomahub.liteflow.builder.prop;
+
+/**
+ * 构建 node 的中间属性
+ */
+public class NodePropBean {
+
+	/**
+	 * id
+	 */
+	String id;
+
+	/**
+	 * 名称
+	 */
+	String name;
+
+	/**
+	 * 类
+	 */
+	String clazz;
+
+	/**
+	 * 脚本
+	 */
+	String script;
+
+	/**
+	 * 类型
+	 */
+	String type;
+
+	/**
+	 * 脚本存放位置
+	 */
+	String file;
+
+	public String getId() {
+		return id;
+	}
+
+	public NodePropBean setId(String id) {
+		this.id = id;
+		return this;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public NodePropBean setName(String name) {
+		this.name = name;
+		return this;
+	}
+
+	public String getClazz() {
+		return clazz;
+	}
+
+	public NodePropBean setClazz(String clazz) {
+		this.clazz = clazz;
+		return this;
+	}
+
+	public String getScript() {
+		return script;
+	}
+
+	public NodePropBean setScript(String script) {
+		this.script = script;
+		return this;
+	}
+
+	public String getType() {
+		return type;
+	}
+
+	public NodePropBean setType(String type) {
+		this.type = type;
+		return this;
+	}
+
+	public String getFile() {
+		return file;
+	}
+
+	public NodePropBean setFile(String file) {
+		this.file = file;
+		return this;
+	}
+}

+ 39 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java

@@ -0,0 +1,39 @@
+package com.yomahub.liteflow.common;
+
+/**
+ * Chain 常量
+ *
+ * @author tangkc
+ */
+public interface ChainConstant {
+
+    String CHAIN = "chain";
+
+    String FLOW = "flow";
+
+    String NODES = "nodes";
+
+    String NODE = "node";
+
+    String ID = "id";
+
+    String _CLASS = "class";
+
+    String FILE = "file";
+
+    String NAME = "name";
+
+    String VALUE = "value";
+
+    String ERROR_RESUME = "errorResume";
+
+    String GROUP = "group";
+
+    String ANY = "any";
+
+    String THREAD_EXECUTOR_CLASS = "threadExecutorClass";
+
+    String CONDITION = "condition";
+
+    String TYPE = "type";
+}

+ 3 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/core/ComponentInitializer.java

@@ -1,5 +1,6 @@
 package com.yomahub.liteflow.core;
 
+import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.annotation.LiteflowRetry;
@@ -42,7 +43,8 @@ public class ComponentInitializer {
         //先取传进来的name值(配置文件中配置的),再看有没有配置@LiteflowComponent标注
         //@LiteflowComponent标注只在spring体系下生效,这里用了spi机制取到相应环境下的实现类
         nodeComponent.setName(desc);
-        if (nodeComponent.getType().equals(NodeTypeEnum.COMMON) && StrUtil.isBlank(nodeComponent.getName())){
+        if (ListUtil.toList(NodeTypeEnum.COMMON, NodeTypeEnum.SWITCH).contains(type)
+                && StrUtil.isBlank(nodeComponent.getName())){
             String name = LiteflowComponentSupportHolder.loadLiteflowComponentSupport().getCmpName(nodeComponent);
             nodeComponent.setName(name);
         }

+ 149 - 99
liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java

@@ -14,25 +14,31 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ReUtil;
 import cn.hutool.core.util.StrUtil;
 import com.google.common.collect.Lists;
-import com.yomahub.liteflow.slot.DataBus;
-import com.yomahub.liteflow.flow.LiteflowResponse;
-import com.yomahub.liteflow.slot.DefaultContext;
-import com.yomahub.liteflow.slot.Slot;
-import com.yomahub.liteflow.flow.element.Chain;
-import com.yomahub.liteflow.flow.element.Node;
 import com.yomahub.liteflow.enums.FlowParserTypeEnum;
 import com.yomahub.liteflow.exception.*;
 import com.yomahub.liteflow.flow.FlowBus;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.flow.element.Chain;
+import com.yomahub.liteflow.flow.element.Node;
 import com.yomahub.liteflow.parser.*;
+import com.yomahub.liteflow.parser.base.FlowParser;
+import com.yomahub.liteflow.parser.el.*;
 import com.yomahub.liteflow.property.LiteflowConfig;
 import com.yomahub.liteflow.property.LiteflowConfigGetter;
+import com.yomahub.liteflow.slot.DataBus;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.slot.Slot;
 import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
+import com.yomahub.liteflow.spi.holder.ContextCmpInitHolder;
 import com.yomahub.liteflow.thread.ExecutorHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.*;
-import java.util.concurrent.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Future;
 
 /**
  * 流程规则主要执行器类
@@ -46,13 +52,30 @@ public class FlowExecutor {
     private static final String ZK_CONFIG_REGEX = "[\\w\\d][\\w\\d\\.]+\\:(\\d)+(\\,[\\w\\d][\\w\\d\\.]+\\:(\\d)+)*";
 
     private static final String LOCAL_XML_CONFIG_REGEX = "^[\\w\\:\\-\\@\\/\\\\\\*]+\\.xml$";
+
+    private static final String LOCAL_EL_XML_CONFIG_REGEX = "^[\\w\\:\\-\\@\\/\\\\\\*]+\\.el\\.xml$";
     private static final String LOCAL_JSON_CONFIG_REGEX = "^[\\w\\:\\-\\@\\/\\\\\\*]+\\.json$";
+
+    private static final String LOCAL_EL_JSON_CONFIG_REGEX = "^[\\w\\:\\-\\@\\/\\\\\\*]+\\.el\\.json$";
     private static final String LOCAL_YML_CONFIG_REGEX = "^[\\w\\:\\-\\@\\/\\\\\\*]+\\.yml$";
 
+    private static final String LOCAL_EL_YML_CONFIG_REGEX = "^[\\w\\:\\-\\@\\/\\\\\\*]+\\.el\\.yml$";
+
     private static final String FORMATE_XML_CONFIG_REGEX = "xml:.+";
+
+    private static final String FORMATE_EL_XML_CONFIG_REGEX = "el_xml:.+";
+
     private static final String FORMATE_JSON_CONFIG_REGEX = "json:.+";
+
+    private static final String FORMATE_EL_JSON_CONFIG_REGEX = "el_json:.+";
+
     private static final String FORMATE_YML_CONFIG_REGEX = "yml:.+";
-    private static final String PREFIX_FORMATE_CONFIG_REGEX = "xml:|json:|yml:";
+
+    private static final String FORMATE_EL_YML_CONFIG_REGEX = "el_yml:.+";
+
+    private static final String PREFIX_FORMAT_CONFIG_REGEX = "xml:|json:|yml:";
+
+    private static final String PREFIX_EL_FORMAT_CONFIG_REGEX = "el_xml:|el_json:|el_yml:";
 
     private static final String CLASS_CONFIG_REGEX = "^\\w+(\\.\\w+)*$";
 
@@ -65,13 +88,13 @@ public class FlowExecutor {
         DataBus.init();
     }
 
-    public FlowExecutor(LiteflowConfig liteflowConfig){
+    public FlowExecutor(LiteflowConfig liteflowConfig) {
         this.liteflowConfig = liteflowConfig;
         //把liteFlowConfig设到LiteFlowGetter中去
         LiteflowConfigGetter.setLiteflowConfig(liteflowConfig);
         //设置FlowExecutor的Holder,虽然大部分地方都可以通过Spring上下文获取到,但放入Holder,还是为了某些地方能方便的取到
         FlowExecutorHolder.setHolder(this);
-        if (liteflowConfig.isParseOnStart()){
+        if (BooleanUtil.isTrue(liteflowConfig.isParseOnStart())) {
             this.init();
         }
         //初始化DataBus
@@ -86,7 +109,14 @@ public class FlowExecutor {
             throw new ConfigErrorException("config error, please check liteflow config property");
         }
 
-        if (StrUtil.isBlank(liteflowConfig.getRuleSource())){
+        //在相应的环境下进行节点的初始化工作
+        //在spring体系下会获得spring扫描后的节点,接入元数据
+        //在非spring体系下是一个空实现,等于不做此步骤
+        ContextCmpInitHolder.loadContextCmpInit().initCmp();
+
+        //如果没有配置规则文件路径,就停止初始化。
+        //规则文件路径不是一定要有,因为liteflow分基于规则和基于代码两种,有可能是动态代码构建的
+        if (StrUtil.isBlank(liteflowConfig.getRuleSource())) {
             return;
         }
 
@@ -97,38 +127,37 @@ public class FlowExecutor {
         List<String> rulePathList = new ArrayList<>();
         for (String path : sourceRulePathList) {
             try {
+                //根据path获得pattern类型
                 FlowParserTypeEnum pattern = matchFormatConfig(path);
-                if (ObjectUtil.isNotNull(pattern)) {
-                    path = ReUtil.replaceAll(path, PREFIX_FORMATE_CONFIG_REGEX, "");
-                    switch (pattern) {
-                        case TYPE_XML:
-                            parser = matchFormatParser(path, FlowParserTypeEnum.TYPE_XML);
-                            parserNameSet.add(parser.getClass().getName());
-                            break;
-                        case TYPE_JSON:
-                            parser = matchFormatParser(path, FlowParserTypeEnum.TYPE_JSON);
-                            parserNameSet.add(parser.getClass().getName());
-                            break;
-                        case TYPE_YML:
-                            parser = matchFormatParser(path, FlowParserTypeEnum.TYPE_YML);
-                            parserNameSet.add(parser.getClass().getName());
-                            break;
-                        default:
-                            String errorMsg = StrUtil.format("can't support the format {}", path);
-                            throw new ErrorSupportPathException(errorMsg);
-                    }
+                if (pattern == null){
+                    String errorMsg = StrUtil.format("can't support the path:{}", path);
+                    throw new ErrorSupportPathException(errorMsg);
+                }
+
+                if (pattern.getType().startsWith("el")){
+                    path = ReUtil.replaceAll(path, PREFIX_EL_FORMAT_CONFIG_REGEX, "");
+                }else{
+                    path = ReUtil.replaceAll(path, PREFIX_FORMAT_CONFIG_REGEX, "");
+                }
+
+
+                //获得parser
+                parser = matchFormatParser(path, pattern);
+
+                if (parser == null){
+                    String errorMsg = StrUtil.format("can't find the parser for path:{}", path);
+                    throw new ErrorSupportPathException(errorMsg);
                 }
+
+                parserNameSet.add(parser.getClass().getName());
+
                 rulePathList.add(path);
 
                 //支持多类型的配置文件,分别解析
-                if (liteflowConfig.isSupportMultipleType()) {
-                    if (ObjectUtil.isNotNull(parser)) {
-                        parser.parseMain(ListUtil.toList(path));
-                    } else {
-                        throw new ConfigErrorException("parse error, please check liteflow config property");
-                    }
+                if (BooleanUtil.isTrue(liteflowConfig.isSupportMultipleType())) {
+                    parser.parseMain(ListUtil.toList(path));
                 }
-            } catch (CyclicDependencyException e){
+            } catch (CyclicDependencyException e) {
                 LOG.error(e.getMessage());
                 throw e;
             } catch (Exception e) {
@@ -139,22 +168,25 @@ public class FlowExecutor {
         }
 
         //单类型的配置文件,需要一起解析
-        if (!liteflowConfig.isSupportMultipleType()){
+        if (BooleanUtil.isFalse(liteflowConfig.isSupportMultipleType())) {
             //检查Parser是否只有一个,因为多个不同的parser会造成子流程的混乱
-            if (parserNameSet.size() > 1){
+            if (parserNameSet.size() > 1) {
                 String errorMsg = "cannot have multiple different parsers";
                 LOG.error(errorMsg);
                 throw new MultipleParsersException(errorMsg);
             }
 
             //进行多个配置文件的一起解析
-            try{
-                if (ObjectUtil.isNotNull(parser)) {
+            try {
+                if (parser != null) {
                     parser.parseMain(rulePathList);
                 } else {
                     throw new ConfigErrorException("parse error, please check liteflow config property");
                 }
-            } catch (CyclicDependencyException e){
+            } catch (CyclicDependencyException e) {
+                LOG.error(e.getMessage());
+                throw e;
+            } catch (ChainDuplicateException e) {
                 LOG.error(e.getMessage());
                 throw e;
             } catch (Exception e) {
@@ -179,6 +211,12 @@ public class FlowExecutor {
                     return new LocalJsonFlowParser();
                 case TYPE_YML:
                     return new LocalYmlFlowParser();
+                case TYPE_EL_XML:
+                    return new LocalXmlFlowELParser();
+                case TYPE_EL_JSON:
+                    return new LocalJsonFlowELParser();
+                case TYPE_EL_YML:
+                    return new LocalYmlFlowELParser();
                 default:
             }
         } else if (isClassConfig(path)) {
@@ -191,6 +229,12 @@ public class FlowExecutor {
                     return (JsonFlowParser) ContextAwareHolder.loadContextAware().registerBean(c);
                 case TYPE_YML:
                     return (YmlFlowParser) ContextAwareHolder.loadContextAware().registerBean(c);
+                case TYPE_EL_XML:
+                    return (XmlFlowELParser) ContextAwareHolder.loadContextAware().registerBean(c);
+                case TYPE_EL_JSON:
+                    return (JsonFlowELParser) ContextAwareHolder.loadContextAware().registerBean(c);
+                case TYPE_EL_YML:
+                    return (YmlFlowELParser) ContextAwareHolder.loadContextAware().registerBean(c);
                 default:
             }
         } else if (isZKConfig(path)) {
@@ -202,6 +246,12 @@ public class FlowExecutor {
                     return new ZookeeperJsonFlowParser(liteflowConfig.getZkNode());
                 case TYPE_YML:
                     return new ZookeeperYmlFlowParser(liteflowConfig.getZkNode());
+                case TYPE_EL_XML:
+                    return new ZookeeperXmlFlowELParser(liteflowConfig.getZkNode());
+                case TYPE_EL_JSON:
+                    return new ZookeeperJsonFlowELParser(liteflowConfig.getZkNode());
+                case TYPE_EL_YML:
+                    return new ZookeeperYmlFlowELParser(liteflowConfig.getZkNode());
                 default:
             }
         }
@@ -215,7 +265,10 @@ public class FlowExecutor {
     private boolean isLocalConfig(String path) {
         return ReUtil.isMatch(LOCAL_XML_CONFIG_REGEX, path)
                 || ReUtil.isMatch(LOCAL_JSON_CONFIG_REGEX, path)
-                || ReUtil.isMatch(LOCAL_YML_CONFIG_REGEX, path);
+                || ReUtil.isMatch(LOCAL_YML_CONFIG_REGEX, path)
+                || ReUtil.isMatch(LOCAL_EL_XML_CONFIG_REGEX, path)
+                || ReUtil.isMatch(LOCAL_EL_JSON_CONFIG_REGEX, path)
+                || ReUtil.isMatch(LOCAL_EL_YML_CONFIG_REGEX, path);
     }
 
     /**
@@ -242,7 +295,15 @@ public class FlowExecutor {
             return FlowParserTypeEnum.TYPE_JSON;
         } else if (ReUtil.isMatch(LOCAL_YML_CONFIG_REGEX, path) || ReUtil.isMatch(FORMATE_YML_CONFIG_REGEX, path)) {
             return FlowParserTypeEnum.TYPE_YML;
+        } else if (ReUtil.isMatch(LOCAL_EL_XML_CONFIG_REGEX, path) || ReUtil.isMatch(FORMATE_EL_XML_CONFIG_REGEX, path)) {
+            return FlowParserTypeEnum.TYPE_EL_XML;
+        } else if (ReUtil.isMatch(LOCAL_EL_JSON_CONFIG_REGEX, path) || ReUtil.isMatch(FORMATE_EL_JSON_CONFIG_REGEX, path)) {
+            return FlowParserTypeEnum.TYPE_EL_JSON;
+        } else if (ReUtil.isMatch(LOCAL_EL_YML_CONFIG_REGEX, path) || ReUtil.isMatch(FORMATE_EL_YML_CONFIG_REGEX, path)) {
+            return FlowParserTypeEnum.TYPE_EL_YML;
         } else if (isClassConfig(path)) {
+            //其实整个这个判断块代码可以不要,因为如果是自定义配置源的话,标准写法也要在前面加xml:/json:/yml:这种
+            //但是这块可能是考虑到有些人忘加了,所以再来判断下。如果写了标准的话,是不会走到这块来的
             try {
                 Class<?> clazz = Class.forName(path);
                 if (ClassXmlFlowParser.class.isAssignableFrom(clazz)) {
@@ -251,6 +312,12 @@ public class FlowExecutor {
                     return FlowParserTypeEnum.TYPE_JSON;
                 } else if (ClassYmlFlowParser.class.isAssignableFrom(clazz)) {
                     return FlowParserTypeEnum.TYPE_YML;
+                } else if (ClassXmlFlowELParser.class.isAssignableFrom(clazz)) {
+                    return FlowParserTypeEnum.TYPE_EL_XML;
+                } else if (ClassJsonFlowELParser.class.isAssignableFrom(clazz)) {
+                    return FlowParserTypeEnum.TYPE_EL_JSON;
+                } else if (ClassYmlFlowELParser.class.isAssignableFrom(clazz)) {
+                    return FlowParserTypeEnum.TYPE_EL_YML;
                 }
             } catch (ClassNotFoundException e) {
                 LOG.error(e.getMessage());
@@ -267,10 +334,13 @@ public class FlowExecutor {
 
     //隐式流程的调用方法
     public void invoke(String chainId, Object param, Integer slotIndex) throws Exception {
-        this.execute(chainId, param, null, slotIndex, true);
+        LiteflowResponse response = this.execute2Resp(chainId, param, null, slotIndex, true);
+        if (!response.isSuccess()){
+            throw response.getCause();
+        }
     }
 
-    public <T> LiteflowResponse<T> invoke2Resp(String chainId, Object param, Integer slotIndex){
+    public LiteflowResponse invoke2Resp(String chainId, Object param, Integer slotIndex) {
         return this.execute2Resp(chainId, param, null, slotIndex, true);
     }
 
@@ -280,51 +350,42 @@ public class FlowExecutor {
         node.execute(slotIndex);
     }
 
-    public DefaultContext execute(String chainId) throws Exception {
-        return this.execute(chainId, null, DefaultContext.class, null, false);
-    }
-
-    public DefaultContext execute(String chainId, Object param) throws Exception {
-        return this.execute(chainId, param, DefaultContext.class, null, false);
-    }
-
-    public <T> T execute(String chainId, Object param, Class<T> contextBeanClazz) throws Exception {
-        return this.execute(chainId, param, contextBeanClazz, null, false);
-    }
-
-    private <T> T execute(String chainId, Object param, Class<T> contextBeanClazz,
-                                      Integer slotIndex, boolean isInnerChain) throws Exception {
-        Slot<T> slot = this.doExecute(chainId, param, contextBeanClazz, slotIndex, isInnerChain);
-        if (ObjectUtil.isNotNull(slot.getException())) {
-            throw slot.getException();
-        } else {
-            return slot.getContextBean();
-        }
-    }
-
-    public LiteflowResponse<DefaultContext> execute2Resp(String chainId) {
+    //调用一个流程并返回LiteflowResponse,上下文为默认的DefaultContext,初始参数为null
+    public LiteflowResponse execute2Resp(String chainId) {
         return this.execute2Resp(chainId, null, DefaultContext.class);
     }
 
-    public LiteflowResponse<DefaultContext> execute2Resp(String chainId, Object param) {
+    //调用一个流程并返回LiteflowResponse,上下文为默认的DefaultContext
+    public LiteflowResponse execute2Resp(String chainId, Object param) {
         return this.execute2Resp(chainId, param, DefaultContext.class);
     }
 
-    public <T> LiteflowResponse<T> execute2Resp(String chainId, Object param, Class<T> contextBeanClazz) {
-        return this.execute2Resp(chainId, param, contextBeanClazz, null, false);
+    //调用一个流程并返回LiteflowResponse,允许多上下文的传入
+    public LiteflowResponse execute2Resp(String chainId, Object param, Class<?>... contextBeanClazzArray) {
+        return this.execute2Resp(chainId, param, contextBeanClazzArray, null, false);
     }
 
-    public <T> Future<LiteflowResponse<T>> execute2Future(String chainId, Object param, Class<T> contextBeanClazz) {
+    //调用一个流程并返回Future<LiteflowResponse>,允许多上下文的传入
+    public Future<LiteflowResponse> execute2Future(String chainId, Object param, Class<?>... contextBeanClazzArray) {
         return ExecutorHelper.loadInstance().buildMainExecutor(liteflowConfig.getMainExecutorClass()).submit(()
-                -> FlowExecutorHolder.loadInstance().execute2Resp(chainId, param, contextBeanClazz, null, false));
+                -> FlowExecutorHolder.loadInstance().execute2Resp(chainId, param, contextBeanClazzArray, null, false));
+    }
 
+    //调用一个流程,返回默认的上下文,适用于简单的调用
+    public DefaultContext execute(String chainId, Object param) throws Exception{
+        LiteflowResponse response = this.execute2Resp(chainId, param, DefaultContext.class);
+        if (!response.isSuccess()){
+            throw response.getCause();
+        }else{
+            return response.getFirstContextBean();
+        }
     }
 
-    public <T> LiteflowResponse<T> execute2Resp(String chainId, Object param, Class<T> contextBeanClazz,
-                                                Integer slotIndex, boolean isInnerChain) {
-        LiteflowResponse<T> response = new LiteflowResponse<>();
+    private LiteflowResponse execute2Resp(String chainId, Object param, Class<?>[] contextBeanClazzArray,
+                                          Integer slotIndex, boolean isInnerChain) {
+        LiteflowResponse response = new LiteflowResponse();
 
-        Slot<T> slot = doExecute(chainId, param, contextBeanClazz, slotIndex, isInnerChain);
+        Slot slot = doExecute(chainId, param, contextBeanClazzArray, slotIndex, isInnerChain);
 
         if (ObjectUtil.isNotNull(slot.getException())) {
             response.setSuccess(false);
@@ -337,15 +398,15 @@ public class FlowExecutor {
         return response;
     }
 
-    private <T> Slot<T> doExecute(String chainId, Object param, Class<T> contextBeanClazz, Integer slotIndex,
-                                         boolean isInnerChain) {
+    private Slot doExecute(String chainId, Object param, Class<?>[] contextBeanClazzArray, Integer slotIndex,
+                           boolean isInnerChain) {
         if (FlowBus.needInit()) {
             init();
         }
 
         if (!isInnerChain && ObjectUtil.isNull(slotIndex)) {
-            slotIndex = DataBus.offerSlot(contextBeanClazz);
-            if (BooleanUtil.isTrue(liteflowConfig.getPrintExecutionLog())){
+            slotIndex = DataBus.offerSlot(ListUtil.toList(contextBeanClazzArray));
+            if (BooleanUtil.isTrue(liteflowConfig.getPrintExecutionLog())) {
                 LOG.info("slot[{}] offered", slotIndex);
             }
         }
@@ -354,24 +415,24 @@ public class FlowExecutor {
             throw new NoAvailableSlotException("there is no available slot");
         }
 
-        Slot<T> slot = DataBus.getSlot(slotIndex);
+        Slot slot = DataBus.getSlot(slotIndex);
         if (ObjectUtil.isNull(slot)) {
             throw new NoAvailableSlotException(StrUtil.format("the slot[{}] is not exist", slotIndex));
         }
 
         if (StrUtil.isBlank(slot.getRequestId())) {
             slot.generateRequestId();
-            if (BooleanUtil.isTrue(liteflowConfig.getPrintExecutionLog())){
+            if (BooleanUtil.isTrue(liteflowConfig.getPrintExecutionLog())) {
                 LOG.info("requestId[{}] has generated", slot.getRequestId());
             }
         }
 
         if (!isInnerChain) {
-            if (ObjectUtil.isNotNull(param)){
+            if (ObjectUtil.isNotNull(param)) {
                 slot.setRequestData(param);
             }
         } else {
-            if (ObjectUtil.isNotNull(param)){
+            if (ObjectUtil.isNotNull(param)) {
                 slot.setChainReqData(chainId, param);
             }
         }
@@ -384,31 +445,20 @@ public class FlowExecutor {
                 String errorMsg = StrUtil.format("[{}]:couldn't find chain with the id[{}]", slot.getRequestId(), chainId);
                 throw new ChainNotFoundException(errorMsg);
             }
-            // 执行前置
-            chain.executePre(slotIndex);
             // 执行chain
             chain.execute(slotIndex);
         } catch (ChainEndException e) {
-            if (ObjectUtil.isNotNull(chain)){
+            if (ObjectUtil.isNotNull(chain)) {
                 String warnMsg = StrUtil.format("[{}]:chain[{}] execute end on slot[{}]", slot.getRequestId(), chain.getChainName(), slotIndex);
                 LOG.warn(warnMsg);
             }
         } catch (Exception e) {
-            if (ObjectUtil.isNotNull(chain)){
+            if (ObjectUtil.isNotNull(chain)) {
                 String errMsg = StrUtil.format("[{}]:chain[{}] execute error on slot[{}]", slot.getRequestId(), chain.getChainName(), slotIndex);
                 LOG.error(errMsg, e);
             }
             slot.setException(e);
         } finally {
-            try{
-                if (ObjectUtil.isNotNull(chain)){
-                    chain.executeFinally(slotIndex);
-                }
-            }catch (Exception e){
-                String errMsg = StrUtil.format("[{}]:an exception occurred during the finally Component execution in chain[{}]", slot.getRequestId(), chain.getChainName());
-                LOG.error(errMsg, e);
-            }
-
             if (!isInnerChain) {
                 slot.printStep();
                 DataBus.releaseSlot(slotIndex);

+ 36 - 35
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java

@@ -8,19 +8,16 @@
 package com.yomahub.liteflow.core;
 
 import cn.hutool.core.date.StopWatch;
-import cn.hutool.core.util.BooleanUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.ttl.TransmittableThreadLocal;
+import com.yomahub.liteflow.flow.LiteflowResponse;
 import com.yomahub.liteflow.flow.executor.NodeExecutor;
 import com.yomahub.liteflow.flow.executor.DefaultNodeExecutor;
 import com.yomahub.liteflow.enums.NodeTypeEnum;
-import com.yomahub.liteflow.property.LiteflowConfig;
-import com.yomahub.liteflow.property.LiteflowConfigGetter;
 import com.yomahub.liteflow.spi.holder.CmpAroundAspectHolder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
 import com.yomahub.liteflow.flow.entity.CmpStep;
 import com.yomahub.liteflow.enums.CmpStepTypeEnum;
 import com.yomahub.liteflow.slot.DataBus;
@@ -39,14 +36,8 @@ public abstract class NodeComponent{
 
 	private final Logger LOG = LoggerFactory.getLogger(this.getClass());
 
-	private final TransmittableThreadLocal<Integer> slotIndexTL = new TransmittableThreadLocal<>();
-
 	private MonitorBus monitorBus;
 
-	private final TransmittableThreadLocal<String> tagTL = new TransmittableThreadLocal<>();
-
-	private final TransmittableThreadLocal<Map<String, Executable>> condNodeMapTL = new TransmittableThreadLocal<>();
-
 	private String nodeId;
 
 	private String name;
@@ -66,15 +57,22 @@ public abstract class NodeComponent{
 	/** 节点执行器的类全名 */
 	private Class<? extends NodeExecutor> nodeExecutorClass = DefaultNodeExecutor.class;
 
+	/********************以下的属性为线程附加属性,并非不变属性********************/
+
+	//当前slot的index
+	private final TransmittableThreadLocal<Integer> slotIndexTL = new TransmittableThreadLocal<>();
 
 	//是否结束整个流程,这个只对串行流程有效,并行流程无效
 	private final TransmittableThreadLocal<Boolean> isEndTL = new TransmittableThreadLocal<>();
 
+	//tag标签
+	private final TransmittableThreadLocal<String> tagTL = new TransmittableThreadLocal<>();
+
 	public NodeComponent() {
 	}
 
 	public void execute() throws Exception{
-		Slot<?> slot = this.getSlot();
+		Slot slot = this.getSlot();
 
 		//在元数据里加入step信息
 		CmpStep cmpStep = new CmpStep(nodeId, name, CmpStepTypeEnum.SINGLE);
@@ -106,14 +104,14 @@ public abstract class NodeComponent{
 			try{
 				self.onError();
 			}catch (Exception ex){
-				String errMsg = StrUtil.format("[{}]:componnet[{}] onError method happens exception",slot.getRequestId(),this.getClass().getSimpleName());
+				String errMsg = StrUtil.format("[{}]:component[{}] onError method happens exception",slot.getRequestId(),this.getDisplayName());
 				LOG.error(errMsg, ex);
 			}
 			throw e;
 		} finally {
 			stopWatch.stop();
 			final long timeSpent = stopWatch.getTotalTimeMillis();
-			LOG.debug("[{}]:componnet[{}] finished in {} milliseconds",slot.getRequestId(),this.getClass().getSimpleName(),timeSpent);
+			LOG.debug("[{}]:component[{}] finished in {} milliseconds",slot.getRequestId(),this.getDisplayName(),timeSpent);
 
 			//往CmpStep中放入时间消耗信息
 			cmpStep.setTimeSpent(timeSpent);
@@ -127,21 +125,9 @@ public abstract class NodeComponent{
 				monitorBus.addStatistics(statistics);
 			}
 		}
-
-		if (this instanceof NodeCondComponent) {
-			String condNodeId = slot.getCondResult(this.getClass().getName());
-			if (StrUtil.isNotBlank(condNodeId)) {
-				Executable condExecutor = this.condNodeMapTL.get().get(condNodeId);
-				if (ObjectUtil.isNotNull(condExecutor)) {
-					condExecutor.execute(slotIndexTL.get());
-				}
-			}
-		}
-
-
 	}
 
-	public <T> void beforeProcess(String nodeId, Slot<T> slot){
+	public <T> void beforeProcess(String nodeId, Slot slot){
 		//全局切面只在spring体系下生效,这里用了spi机制取到相应环境下的实现类
 		//非spring环境下,全局切面为空实现
 		CmpAroundAspectHolder.loadCmpAroundAspect().beforeProcess(nodeId, slot);
@@ -157,7 +143,7 @@ public abstract class NodeComponent{
 		//如果需要在抛错后回调某一段逻辑,请覆盖这个方法
 	}
 
-	public <T> void afterProcess(String nodeId, Slot<T> slot){
+	public <T> void afterProcess(String nodeId, Slot slot){
 		CmpAroundAspectHolder.loadCmpAroundAspect().afterProcess(nodeId, slot);
 	}
 
@@ -203,13 +189,16 @@ public abstract class NodeComponent{
 		this.slotIndexTL.remove();
 	}
 
-	public <T> Slot<T> getSlot(){
+	public Slot getSlot(){
 		return DataBus.getSlot(this.slotIndexTL.get());
 	}
 
-	public <T> T getContextBean(){
-		Slot<T> slot = this.getSlot();
-		return slot.getContextBean();
+	public <T> T getFirstContextBean(){
+		return this.getSlot().getFirstContextBean();
+	}
+
+	public <T> T getContextBean(Class<T> contextBeanClazz){
+		return this.getSlot().getContextBean(contextBeanClazz);
 	}
 
 	public String getNodeId() {
@@ -284,10 +273,6 @@ public abstract class NodeComponent{
 		return this.tagTL.get();
 	}
 
-	public void setCondNodeMap(Map<String, Executable> condNodeMap){
-		this.condNodeMapTL.set(condNodeMap);
-	}
-
 	public MonitorBus getMonitorBus() {
 		return monitorBus;
 	}
@@ -307,4 +292,20 @@ public abstract class NodeComponent{
 	public String getChainName(){
 		return getSlot().getChainName();
 	}
+
+	public String getDisplayName(){
+		if(StrUtil.isEmpty(this.name)){
+			return this.nodeId;
+		}else {
+			return StrUtil.format("{}({})", this.nodeId, this.name);
+		}
+	}
+
+	public void invoke(String chainId, Object param) throws Exception {
+		FlowExecutorHolder.loadInstance().invoke(chainId, param, this.getSlotIndex());
+	}
+
+	public LiteflowResponse invoke2Resp(String chainId, Object param, Integer slotIndex) {
+		return FlowExecutorHolder.loadInstance().invoke2Resp(chainId, param, this.getSlotIndex());
+	}
 }

+ 4 - 4
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeCondComponent.java → liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeSwitchComponent.java

@@ -11,15 +11,15 @@ package com.yomahub.liteflow.core;
  * 条件路由节点抽象类
  * @author Bryan.Zhang
  */
-public abstract class NodeCondComponent extends NodeComponent {
+public abstract class NodeSwitchComponent extends NodeComponent {
 
 	@Override
 	public void process() throws Exception {
-		String nodeId = this.processCond();
-		this.getSlot().setCondResult(this.getClass().getName(), nodeId);
+		String nodeId = this.processSwitch();
+		this.getSlot().setSwitchResult(this.getClass().getName(), nodeId);
 	}
 
 	//用以返回路由节点的beanId
-	public abstract String processCond() throws Exception;
+	public abstract String processSwitch() throws Exception;
 
 }

+ 1 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptComponent.java

@@ -19,7 +19,7 @@ public class ScriptComponent extends NodeComponent{
     }
 
     public void loadScript(String script) {
-        log.info("load script for component[{}]", getNodeId());
+        log.info("load script for component[{}]", getDisplayName());
         ScriptExecutorFactory.loadInstance().getScriptExecutor().load(getNodeId(), script);
     }
 }

+ 2 - 2
liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptCondComponent.java → liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptSwitchComponent.java

@@ -7,10 +7,10 @@ import com.yomahub.liteflow.script.ScriptExecutorFactory;
  * @author Bryan.Zhang
  * @since 2.6.0
  */
-public class ScriptCondComponent extends NodeCondComponent{
+public class ScriptSwitchComponent extends NodeSwitchComponent {
 
     @Override
-    public String processCond() throws Exception {
+    public String processSwitch() throws Exception {
         return (String)ScriptExecutorFactory.loadInstance().getScriptExecutor().execute(getNodeId(), getSlotIndex());
     }
 

+ 2 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/enums/ConditionTypeEnum.java

@@ -3,6 +3,8 @@ package com.yomahub.liteflow.enums;
 public enum ConditionTypeEnum {
     TYPE_THEN("then","then"),
     TYPE_WHEN("when","when"),
+
+    TYPE_SWITCH("switch", "switch"),
     TYPE_PRE("pre","pre"),
     TYPE_FINALLY("finally","finally")
     ;

+ 1 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/enums/ExecuteTypeEnum.java

@@ -12,5 +12,5 @@ package com.yomahub.liteflow.enums;
  * @author Bryan.Zhang
  */
 public enum ExecuteTypeEnum {
-    CHAIN,NODE
+    CHAIN,CONDITION,NODE
 }

+ 7 - 4
liteflow-core/src/main/java/com/yomahub/liteflow/enums/FlowParserTypeEnum.java

@@ -5,10 +5,13 @@ package com.yomahub.liteflow.enums;
  * @since 2.5.0
  */
 public enum FlowParserTypeEnum {
-    TYPE_XML("xml","xml"),
-    TYPE_YML("yml","yml"),
-    TYPE_JSON("json","json")
-            ;
+    TYPE_XML("xml", "xml"),
+    TYPE_YML("yml", "yml"),
+    TYPE_JSON("json", "json"),
+    TYPE_EL_XML("el_xml", "el_xml"),
+    TYPE_EL_JSON("el_json", "el_json"),
+    TYPE_EL_YML("el_yml", "el_yml")
+    ;
     private String type;
     private String name;
 

+ 1 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/enums/LiteFlowMethodEnum.java

@@ -2,7 +2,7 @@ package com.yomahub.liteflow.enums;
 
 public enum LiteFlowMethodEnum {
     PROCESS("process"),
-    PROCESS_COND("processCond"),
+    PROCESS_SWITCH("processSwitch"),
     IS_ACCESS("isAccess"),
 
     IS_END("isEnd"),

+ 3 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/enums/NodeTypeEnum.java

@@ -7,8 +7,10 @@ package com.yomahub.liteflow.enums;
  */
 public enum NodeTypeEnum {
     COMMON("common","普通"),
+
+    SWITCH("switch", "条件"),
     SCRIPT("script","脚本"),
-    COND_SCRIPT("cond_script","条件脚本")
+    SWITCH_SCRIPT("switch_script","条件脚本")
     ;
     private String code;
     private String name;

+ 30 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ChainDuplicateException.java

@@ -0,0 +1,30 @@
+package com.yomahub.liteflow.exception;
+
+/**
+ * Chain 重复异常
+ *
+ * @author tangkc
+ */
+public class ChainDuplicateException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 异常信息
+     */
+    private String message;
+
+    public ChainDuplicateException(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ChainEndException.java

@@ -12,6 +12,7 @@ public class ChainEndException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ChainNotFoundException.java

@@ -11,6 +11,7 @@ public class ChainNotFoundException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ComponentCannotRegisterException.java

@@ -17,6 +17,7 @@ public class ComponentCannotRegisterException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ComponentMethodDefineErrorException.java

@@ -12,6 +12,7 @@ public class ComponentMethodDefineErrorException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ComponentNotAccessException.java

@@ -11,6 +11,7 @@ public class ComponentNotAccessException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ComponentProxyErrorException.java

@@ -12,6 +12,7 @@ public class ComponentProxyErrorException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ConfigErrorException.java

@@ -11,6 +11,7 @@ public class ConfigErrorException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/CyclicDependencyException.java

@@ -12,6 +12,7 @@ public class CyclicDependencyException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 25 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ELParseException.java

@@ -0,0 +1,25 @@
+package com.yomahub.liteflow.exception;
+
+public class ELParseException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 异常信息
+     */
+    private String message;
+
+    public ELParseException(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/EmptyConditionValueException.java

@@ -11,6 +11,7 @@ public class EmptyConditionValueException extends RuntimeException {
         this.message = message;
     }
 
+    @Override
     public String getMessage() {
         return message;
     }

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ErrorSupportPathException.java

@@ -11,6 +11,7 @@ public class ErrorSupportPathException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ExecutableItemNotFoundException.java

@@ -21,6 +21,7 @@ public class ExecutableItemNotFoundException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/FlowExecutorNotInitException.java

@@ -11,6 +11,7 @@ public class FlowExecutorNotInitException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/FlowSystemException.java

@@ -11,6 +11,7 @@ public class FlowSystemException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/MultipleParsersException.java

@@ -11,6 +11,7 @@ public class MultipleParsersException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/NoAvailableSlotException.java

@@ -11,6 +11,7 @@ public class NoAvailableSlotException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 30 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/NoSuchContextBeanException.java

@@ -0,0 +1,30 @@
+package com.yomahub.liteflow.exception;
+
+/**
+ * Chain 重复异常
+ *
+ * @author tangkc
+ */
+public class NoSuchContextBeanException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 异常信息
+     */
+    private String message;
+
+    public NoSuchContextBeanException(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+}

+ 25 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/NoSwitchTargetNodeException.java

@@ -0,0 +1,25 @@
+package com.yomahub.liteflow.exception;
+
+public class NoSwitchTargetNodeException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 异常信息
+     */
+    private String message;
+
+    public NoSwitchTargetNodeException(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/NodeBuildException.java

@@ -11,6 +11,7 @@ public class NodeBuildException extends RuntimeException {
         this.message = message;
     }
 
+    @Override
     public String getMessage() {
         return message;
     }

+ 25 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/NodeClassNotFoundException.java

@@ -0,0 +1,25 @@
+package com.yomahub.liteflow.exception;
+
+public class NodeClassNotFoundException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 异常信息
+     */
+    private String message;
+
+    public NodeClassNotFoundException(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+}

+ 25 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/NodeTypeCanNotGuessException.java

@@ -0,0 +1,25 @@
+package com.yomahub.liteflow.exception;
+
+public class NodeTypeCanNotGuessException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 异常信息
+     */
+    private String message;
+
+    public NodeTypeCanNotGuessException(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/NodeTypeNotSupportException.java

@@ -17,6 +17,7 @@ public class NodeTypeNotSupportException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/NotSupportConditionException.java

@@ -11,6 +11,7 @@ public class NotSupportConditionException extends RuntimeException {
         this.message = message;
     }
 
+    @Override
     public String getMessage() {
         return message;
     }

+ 25 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/NullNodeTypeException.java

@@ -0,0 +1,25 @@
+package com.yomahub.liteflow.exception;
+
+public class NullNodeTypeException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 异常信息
+     */
+    private String message;
+
+    public NullNodeTypeException(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ParseException.java

@@ -11,6 +11,7 @@ public class ParseException extends RuntimeException {
 		this.message = message;
 	}
 
+	@Override
 	public String getMessage() {
 		return message;
 	}

+ 22 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ParserCannotFindException.java

@@ -0,0 +1,22 @@
+package com.yomahub.liteflow.exception;
+
+public class ParserCannotFindException extends RuntimeException {
+
+	private static final long serialVersionUID = 1L;
+
+	/** 异常信息 */
+	private String message;
+
+	public ParserCannotFindException(String message) {
+		this.message = message;
+	}
+
+	@Override
+	public String getMessage() {
+		return message;
+	}
+
+	public void setMessage(String message) {
+		this.message = message;
+	}
+}

+ 30 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/RequestIdGeneratorException.java

@@ -0,0 +1,30 @@
+package com.yomahub.liteflow.exception;
+
+/**
+ * RequestIdGenerator 构建异常
+ *
+ * @author tangkc
+ */
+public class RequestIdGeneratorException extends RuntimeException {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 异常信息
+	 */
+	private String message;
+
+	public RequestIdGeneratorException(String message) {
+		this.message = message;
+	}
+
+	@Override
+	public String getMessage() {
+		return message;
+	}
+
+	public void setMessage(String message) {
+		this.message = message;
+	}
+
+}

+ 25 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/SwitchTargetCannotBePreOrFinallyException.java

@@ -0,0 +1,25 @@
+package com.yomahub.liteflow.exception;
+
+public class SwitchTargetCannotBePreOrFinallyException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 异常信息
+     */
+    private String message;
+
+    public SwitchTargetCannotBePreOrFinallyException(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+}

+ 25 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/SwitchTypeErrorException.java

@@ -0,0 +1,25 @@
+package com.yomahub.liteflow.exception;
+
+public class SwitchTypeErrorException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 异常信息
+     */
+    private String message;
+
+    public SwitchTypeErrorException(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ThreadExecutorServiceCreateException.java

@@ -15,6 +15,7 @@ public class ThreadExecutorServiceCreateException extends RuntimeException {
         this.message = message;
     }
 
+    @Override
     public String getMessage() {
         return message;
     }

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/WhenExecuteException.java

@@ -11,6 +11,7 @@ public class WhenExecuteException extends RuntimeException {
         this.message = message;
     }
 
+    @Override
     public String getMessage() {
         return message;
     }

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/WhenTimeoutException.java

@@ -11,6 +11,7 @@ public class WhenTimeoutException extends RuntimeException {
         this.message = message;
     }
 
+    @Override
     public String getMessage() {
         return message;
     }

+ 53 - 13
liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java

@@ -12,10 +12,8 @@ import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
-import com.yomahub.liteflow.core.ComponentInitializer;
-import com.yomahub.liteflow.core.NodeComponent;
-import com.yomahub.liteflow.core.ScriptComponent;
-import com.yomahub.liteflow.core.ScriptCondComponent;
+import com.yomahub.liteflow.core.*;
+import com.yomahub.liteflow.exception.NullNodeTypeException;
 import com.yomahub.liteflow.flow.element.Chain;
 import com.yomahub.liteflow.flow.element.Node;
 import com.yomahub.liteflow.enums.FlowParserTypeEnum;
@@ -24,6 +22,9 @@ import com.yomahub.liteflow.exception.ComponentCannotRegisterException;
 import com.yomahub.liteflow.parser.LocalJsonFlowParser;
 import com.yomahub.liteflow.parser.LocalXmlFlowParser;
 import com.yomahub.liteflow.parser.LocalYmlFlowParser;
+import com.yomahub.liteflow.parser.el.LocalJsonFlowELParser;
+import com.yomahub.liteflow.parser.el.LocalXmlFlowELParser;
+import com.yomahub.liteflow.parser.el.LocalYmlFlowELParser;
 import com.yomahub.liteflow.script.ScriptExecutor;
 import com.yomahub.liteflow.script.ScriptExecutorFactory;
 import com.yomahub.liteflow.script.exception.ScriptSpiException;
@@ -81,7 +82,18 @@ public class FlowBus {
     }
 
     public static void addSpringScanNode(String nodeId, NodeComponent nodeComponent) {
-        nodeMap.put(nodeId, new Node(ComponentInitializer.loadInstance().initComponent(nodeComponent, NodeTypeEnum.COMMON, null, nodeId)));
+        NodeTypeEnum type = null;
+        if (nodeComponent instanceof NodeSwitchComponent){
+            type = NodeTypeEnum.SWITCH;
+        } else if(nodeComponent instanceof NodeComponent){
+            type = NodeTypeEnum.COMMON;
+        }
+
+        if (type == null){
+            throw new NullNodeTypeException(StrUtil.format("node type is null for node[{}]", nodeId));
+        }
+
+        nodeMap.put(nodeId, new Node(ComponentInitializer.loadInstance().initComponent(nodeComponent, type, null, nodeId)));
     }
 
     public static void addCommonNode(String nodeId, String name, String cmpClazzStr){
@@ -94,16 +106,30 @@ public class FlowBus {
         addNode(nodeId, name, NodeTypeEnum.COMMON, cmpClazz, null);
     }
 
-    public static void addCommonNode(String nodeId, String name, Class<? extends NodeComponent> cmpClazz){
+    public static void addCommonNode(String nodeId, String name, Class<?> cmpClazz){
         addNode(nodeId, name, NodeTypeEnum.COMMON, cmpClazz, null);
     }
 
+    public static void addSwitchNode(String nodeId, String name, String cmpClazzStr){
+        Class<?> cmpClazz;
+        try{
+            cmpClazz = Class.forName(cmpClazzStr);
+        }catch (Exception e){
+            throw new ComponentCannotRegisterException(e.getMessage());
+        }
+        addNode(nodeId, name, NodeTypeEnum.SWITCH, cmpClazz, null);
+    }
+
+    public static void addSwitchNode(String nodeId, String name, Class<?> cmpClazz){
+        addNode(nodeId, name, NodeTypeEnum.SWITCH, cmpClazz, null);
+    }
+
     public static void addCommonScriptNode(String nodeId, String name, String script){
         addNode(nodeId, name, NodeTypeEnum.SCRIPT, ScriptComponent.class, script);
     }
 
-    public static void addCondScriptNode(String nodeId, String name, String script){
-        addNode(nodeId, name, NodeTypeEnum.COND_SCRIPT, ScriptCondComponent.class, script);
+    public static void addSwitchScriptNode(String nodeId, String name, String script){
+        addNode(nodeId, name, NodeTypeEnum.SWITCH_SCRIPT, ScriptSwitchComponent.class, script);
     }
 
     private static void addNode(String nodeId, String name, NodeTypeEnum type, Class<?> cmpClazz, String script) {
@@ -111,7 +137,7 @@ public class FlowBus {
             //判断此类是否是声明式的组件,如果是声明式的组件,就用动态代理生成实例
             //如果不是声明式的,就用传统的方式进行判断
             NodeComponent cmpInstance = null;
-            if (LiteFlowProxyUtil.isMarkedCmp(cmpClazz)){
+            if (LiteFlowProxyUtil.isDeclareCmp(cmpClazz)){
                 //这里的逻辑要仔细看下
                 //如果是spring体系,把原始的类往spring上下文中进行注册,那么会走到ComponentScanner中
                 //由于ComponentScanner中已经对原始类进行了动态代理,出来的对象已经变成了动态代理类,所以这时候的bean已经是NodeComponent的子类了
@@ -129,7 +155,7 @@ public class FlowBus {
                 //以node方式配置,本质上是为了适配无spring的环境,如果有spring环境,其实不用这么配置
                 //这里的逻辑是判断是否能从spring上下文中取到,如果没有spring,则就是new instance了
                 //如果是script类型的节点,因为class只有一个,所以也不能注册进spring上下文,注册的时候需要new Instance
-                if (!CollectionUtil.newArrayList(NodeTypeEnum.SCRIPT, NodeTypeEnum.COND_SCRIPT).contains(type)){
+                if (!CollectionUtil.newArrayList(NodeTypeEnum.SCRIPT, NodeTypeEnum.SWITCH_SCRIPT).contains(type)){
                     cmpInstance = (NodeComponent) ContextAwareHolder.loadContextAware().registerOrGet(nodeId, cmpClazz);
                 }
 
@@ -149,14 +175,14 @@ public class FlowBus {
                 node.setScript(script);
                 if (type.equals(NodeTypeEnum.SCRIPT)){
                     ((ScriptComponent)cmpInstance).loadScript(script);
-                }else if(type.equals(NodeTypeEnum.COND_SCRIPT)){
-                    ((ScriptCondComponent)cmpInstance).loadScript(script);
+                }else if(type.equals(NodeTypeEnum.SWITCH_SCRIPT)){
+                    ((ScriptSwitchComponent)cmpInstance).loadScript(script);
                 }
             }
 
             nodeMap.put(nodeId, node);
         } catch (Exception e) {
-            String error = StrUtil.format("component[{}] register error", cmpClazz.getName());
+            String error = StrUtil.format("component[{}] register error", StrUtil.isEmpty(name)?nodeId:StrUtil.format("{}({})",nodeId,name));
             LOG.error(error, e);
             throw new ComponentCannotRegisterException(error);
         }
@@ -178,6 +204,14 @@ public class FlowBus {
         }
     }
 
+    public static Map<String, Node> getNodeMap(){
+        return nodeMap;
+    }
+
+    public static Map<String, Chain> getChainMap(){
+        return chainMap;
+    }
+
     public static void cleanCache() {
         chainMap.clear();
         nodeMap.clear();
@@ -201,6 +235,12 @@ public class FlowBus {
             new LocalJsonFlowParser().parse(content);
         } else if (type.equals(FlowParserTypeEnum.TYPE_YML)) {
             new LocalYmlFlowParser().parse(content);
+        } else if (type.equals(FlowParserTypeEnum.TYPE_EL_XML)) {
+            new LocalXmlFlowELParser().parse(content);
+        } else if (type.equals(FlowParserTypeEnum.TYPE_EL_JSON)) {
+            new LocalJsonFlowELParser().parse(content);
+        } else if (type.equals(FlowParserTypeEnum.TYPE_EL_YML)) {
+            new LocalYmlFlowELParser().parse(content);
         }
     }
 

+ 21 - 13
liteflow-core/src/main/java/com/yomahub/liteflow/flow/LiteflowResponse.java

@@ -13,7 +13,7 @@ import java.util.stream.Collectors;
  * 执行结果封装类
  * @author zend.wang
  */
-public class LiteflowResponse<T> implements Serializable {
+public class LiteflowResponse implements Serializable {
     
     private static final long serialVersionUID = -2792556188993845048L;
     
@@ -21,14 +21,14 @@ public class LiteflowResponse<T> implements Serializable {
     
     private String message;
     
-    private Throwable cause;
+    private Exception cause;
     
-    private Slot<T> slot;
+    private Slot slot;
     
     public LiteflowResponse() {
       this(null);
     }
-    public LiteflowResponse(Slot<T> slot) {
+    public LiteflowResponse(Slot slot) {
         this.success = true;
         this.message = "";
         this.slot = slot;
@@ -50,35 +50,43 @@ public class LiteflowResponse<T> implements Serializable {
         this.message = message;
     }
     
-    public Throwable getCause() {
+    public Exception getCause() {
         return cause;
     }
     
-    public void setCause(final Throwable cause) {
+    public void setCause(final Exception cause) {
         this.cause = cause;
     }
     
-    public Slot<T> getSlot() {
+    public Slot getSlot() {
         return slot;
     }
     
-    public void setSlot(Slot<T> slot) {
+    public void setSlot(Slot slot) {
         this.slot = slot;
     }
 
-    public T getContextBean(){
-        return getSlot().getContextBean();
+    public <T> T getFirstContextBean(){
+        return this.getSlot().getFirstContextBean();
+    }
+
+    public <T> T getContextBean(Class<T> contextBeanClazz){
+        return this.getSlot().getContextBean(contextBeanClazz);
     }
 
     public Map<String, CmpStep> getExecuteSteps(){
-        return getSlot().getExecuteSteps().stream().collect(Collectors.toMap(CmpStep::getNodeId, cmpStep -> cmpStep));
+        return this.getSlot().getExecuteSteps().stream().collect(Collectors.toMap(CmpStep::getNodeId, cmpStep -> cmpStep));
     }
 
     public String getExecuteStepStr(){
-        return getSlot().getExecuteStepStr();
+        return this.getSlot().getExecuteStepStr();
     }
 
     public String getExecuteStepStrWithoutTime(){
-        return getSlot().getExecuteStepStr(false);
+        return this.getSlot().getExecuteStepStr(false);
+    }
+
+    public String getRequestId(){
+        return this.getSlot().getRequestId();
     }
 }

+ 0 - 21
liteflow-core/src/main/java/com/yomahub/liteflow/flow/condition/FinallyCondition.java

@@ -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.flow.condition;
-
-/**
- * 前置Condition
- * @author Bryan.Zhang
- * @since 2.6.4
- */
-public class FinallyCondition extends Condition {
-
-	public FinallyCondition(Condition condition){
-		super(condition.getNodeList());
-		super.setConditionType(condition.getConditionType());
-	}
-}

+ 0 - 21
liteflow-core/src/main/java/com/yomahub/liteflow/flow/condition/PreCondition.java

@@ -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.flow.condition;
-
-/**
- * 前置Condition
- * @author Bryan.Zhang
- * @since 2.6.4
- */
-public class PreCondition extends Condition {
-
-	public PreCondition(Condition condition){
-		super(condition.getNodeList());
-		super.setConditionType(condition.getConditionType());
-	}
-}

+ 0 - 20
liteflow-core/src/main/java/com/yomahub/liteflow/flow/condition/ThenCondition.java

@@ -1,20 +0,0 @@
-/**
- * <p>Title: liteflow</p>
- * <p>Description: 轻量级的组件式流程框架</p>
- * @author Bryan.Zhang
- * @email weenyc31@163.com
- * @Date 2020/4/1
- */
-package com.yomahub.liteflow.flow.condition;
-
-/**
- * 串行器
- * @author Bryan.Zhang
- */
-public class ThenCondition extends Condition {
-
-	public ThenCondition(Condition condition){
-		super(condition.getNodeList());
-		super.setConditionType(condition.getConditionType());
-	}
-}

+ 0 - 25
liteflow-core/src/main/java/com/yomahub/liteflow/flow/condition/WhenCondition.java

@@ -1,25 +0,0 @@
-/**
- * <p>Title: liteflow</p>
- * <p>Description: 轻量级的组件式流程框架</p>
- * @author Bryan.Zhang
- * @email weenyc31@163.com
- * @Date 2020/4/1
- */
-package com.yomahub.liteflow.flow.condition;
-
-/**
- * 并行器
- * @author Bryan.Zhang
- */
-public class WhenCondition extends Condition {
-
-	public WhenCondition(Condition condition) {
-		super(condition.getNodeList());
-		super.setConditionType(condition.getConditionType());
-		super.setGroup(condition.getGroup());
-		super.setErrorResume(condition.isErrorResume());
-		super.setAny(condition.isAny());
-		super.setThreadExecutorClass(condition.getThreadExecutorClass());
-	}
-
-}

+ 43 - 151
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java

@@ -9,34 +9,16 @@
 package com.yomahub.liteflow.flow.element;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.exception.ChainEndException;
 import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.slot.Slot;
-import com.yomahub.liteflow.flow.parallel.CompletableFutureTimeout;
-import com.yomahub.liteflow.flow.parallel.ParallelSupplier;
-import com.yomahub.liteflow.flow.parallel.WhenFutureObj;
-import com.yomahub.liteflow.enums.ConditionTypeEnum;
 import com.yomahub.liteflow.enums.ExecuteTypeEnum;
 import com.yomahub.liteflow.exception.FlowSystemException;
-import com.yomahub.liteflow.exception.WhenExecuteException;
-import com.yomahub.liteflow.flow.condition.Condition;
-import com.yomahub.liteflow.flow.condition.ThenCondition;
-import com.yomahub.liteflow.flow.condition.WhenCondition;
-import com.yomahub.liteflow.property.LiteflowConfig;
-import com.yomahub.liteflow.property.LiteflowConfigGetter;
-import com.yomahub.liteflow.thread.ExecutorHelper;
+import com.yomahub.liteflow.flow.element.condition.Condition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
-import javax.xml.crypto.Data;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
 
 /**
  * chain对象,实现可执行器
@@ -51,6 +33,12 @@ public class Chain implements Executable {
 
     private List<Condition> conditionList = new ArrayList<>();
 
+    //前置处理Condition,用来区别主体的Condition
+    private List<Condition> preConditionList = new ArrayList<>();
+
+    //后置处理Condition,用来区别主体的Condition
+    private List<Condition> finallyConditionList = new ArrayList<>();
+
     public Chain(String chainName){
         this.chainName = chainName;
     }
@@ -84,23 +72,28 @@ public class Chain implements Executable {
         if (CollUtil.isEmpty(conditionList)) {
             throw new FlowSystemException("no conditionList in this chain[" + chainName + "]");
         }
-        Slot<?> slot = DataBus.getSlot(slotIndex);
-        try{
+        Slot slot = DataBus.getSlot(slotIndex);
+        try {
             //在子流程或者隐式流程里,slot需要取到的chainName是当前流程,所以这不再是set,而是push
             //其底层结构是一个stack
             slot.pushChainName(chainName);
-
-            //循环condition进行执行
+            //执行前置
+            this.executePre(slotIndex);
+            //执行主体Condition
             for (Condition condition : conditionList) {
-                if (condition instanceof ThenCondition) {
-                    for (Executable executableItem : condition.getNodeList()) {
-                        executableItem.execute(slotIndex);
-                    }
-                } else if (condition instanceof WhenCondition) {
-                    executeAsyncCondition((WhenCondition) condition, slotIndex);
-                }
+                condition.execute(slotIndex);
             }
+        }catch (ChainEndException e){
+            //这里单独catch ChainEndException是因为ChainEndException是用户自己setIsEnd抛出的异常
+            //是属于正常逻辑,所以会在FlowExecutor中判断。这里不作为异常处理
+            throw e;
+        }catch (Exception e){
+            //这里事先取到exception set到slot里,为了方便finally取到exception
+            slot.setException(e);
+            throw e;
         }finally {
+            //执行后置
+            this.executeFinally(slotIndex);
             //流程结束后,需要把当前的chainName从stack结构中移出
             //里面的逻辑判断了当只剩根chainName的时候,不移除
             slot.popChainName();
@@ -108,30 +101,17 @@ public class Chain implements Executable {
     }
 
     // 执行pre节点
-    public void executePre(Integer slotIndex) throws Exception {
-        doExecuteForPointConditionType(slotIndex, ConditionTypeEnum.TYPE_PRE);
-    }
-
-    public void executeFinally(Integer slotIndex) throws Exception {
-        doExecuteForPointConditionType(slotIndex, ConditionTypeEnum.TYPE_FINALLY);
-    }
-
-    // 执行指定的conditionType的节点
-    private void doExecuteForPointConditionType(Integer slotIndex, ConditionTypeEnum conditionTypeEnum)  throws Exception {
-        //先把指定condition类型的节点过滤出来
-        List<Condition> conditions =filterCondition(conditionTypeEnum);
-        for (Condition condition : conditions){
-            for(Executable executableItem : condition.getNodeList()){
-                executableItem.execute(slotIndex);
-            }
+    private void executePre(Integer slotIndex) throws Exception {
+        for (Condition condition : this.preConditionList){
+            condition.execute(slotIndex);
         }
     }
 
-    // 根据节点condition类型过去出节点列表
-    private List<Condition> filterCondition(ConditionTypeEnum conditionTypeEnum) {
-        assert conditionTypeEnum != null;
-        return  conditionList.stream().filter(condition ->
-                condition.getConditionType().equals(conditionTypeEnum)).collect(Collectors.toList());
+    //执行后置
+    private void executeFinally(Integer slotIndex) throws Exception {
+        for (Condition condition : this.finallyConditionList){
+            condition.execute(slotIndex);
+        }
     }
 
     @Override
@@ -143,107 +123,19 @@ public class Chain implements Executable {
     public String getExecuteName() {
         return chainName;
     }
+    public List<Condition> getPreConditionList() {
+        return preConditionList;
+    }
 
-    //使用线程池执行when并发流程
-    //这块涉及到挺多的多线程逻辑,所以注释比较详细,看到这里的童鞋可以仔细阅读
-    private void executeAsyncCondition(WhenCondition condition, Integer slotIndex) throws Exception{
-        Slot slot = DataBus.getSlot(slotIndex);
-
-        //此方法其实只会初始化一次Executor,不会每次都会初始化。Executor是唯一的
-        ExecutorService parallelExecutor = ExecutorHelper.loadInstance().buildWhenExecutor(condition.getThreadExecutorClass());
-
-        //获得liteflow的参数
-        LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
-
-        //定义是否中断参数
-        //这里为什么要定义成数组呢,因为后面lambda要用到,根据final不能修改引用的原则,这里用了数组对象
-        final boolean[] interrupted = {false};
-
-        //这里主要是做了封装CompletableFuture对象,用lumbda表达式做了很多事情,这句代码要仔细理清
-        //1.根据condition.getNodeList()的集合进行流处理,用map进行把executable对象转换成List<CompletableFuture<WhenFutureObj>>
-        //2.在转的过程中,套入CompletableFutureTimeout方法进行超时判断,如果超时则用WhenFutureObj.timeOut返回超时的对象
-        //3.第2个参数是主要的本体CompletableFuture,传入了ParallelSupplier和线程池对象
-        List<CompletableFuture<WhenFutureObj>> completableFutureList = condition.getNodeList().stream().filter(executable -> {
-            try {
-                return executable.isAccess(slotIndex);
-            }catch (Exception e){
-                LOG.error("there was an error when executing the when component isAccess",e);
-                return false;
-            }
-        }).map(executable -> CompletableFutureTimeout.completeOnTimeout(
-                                    WhenFutureObj.timeOut(executable.getExecuteName()),
-                                    CompletableFuture.supplyAsync(new ParallelSupplier(executable, slotIndex), parallelExecutor),
-                                    liteflowConfig.getWhenMaxWaitSeconds(),
-                                    TimeUnit.SECONDS
-                                  )).collect(Collectors.toList());
-
-
-        CompletableFuture<?> resultCompletableFuture;
-
-        //这里判断执行方式
-        //如果any为false,说明这些异步任务全部执行好或者超时,才返回
-        //如果any为true,说明这些异步任务只要任意一个执行完成,就返回
-        if(condition.isAny()){
-            //把这些CompletableFuture通过anyOf合成一个CompletableFuture
-            resultCompletableFuture = CompletableFuture.anyOf(completableFutureList.toArray(new CompletableFuture[]{}));
-        }else{
-            //把这些CompletableFuture通过allOf合成一个CompletableFuture
-            resultCompletableFuture = CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[]{}));
-        }
-
-        try {
-            //进行执行,这句执行完后,就意味着所有的任务要么执行完毕,要么超时返回
-            resultCompletableFuture.get();
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.error("there was an error when executing the CompletableFuture",e);
-            interrupted[0] = true;
-        }
-
-        //拿到已经完成的CompletableFuture
-        //如果any为false,那么所有任务都已经完成
-        //如果any为true,那么这里拿到的是第一个完成的任务
-        //这里过滤和转换一起用lumbda做了
-        List<WhenFutureObj> allCompletableWhenFutureObjList = completableFutureList.stream().filter(f -> {
-            //过滤出已经完成的,没完成的就直接终止
-            if (f.isDone()){
-                return true;
-            }else{
-                f.cancel(true);
-                return false;
-            }
-        }).map(f -> {
-            try {
-                return f.get();
-            } catch (InterruptedException | ExecutionException e) {
-                interrupted[0] = true;
-                return null;
-            }
-        }).collect(Collectors.toList());
-
-        //判断超时,上面已经拿到了所有已经完成的CompletableFuture
-        //那我们只要过滤出超时的CompletableFuture
-        List<WhenFutureObj> timeOutWhenFutureObjList = allCompletableWhenFutureObjList.stream().filter(WhenFutureObj::isTimeout).collect(Collectors.toList());
-
-        //输出超时信息
-        timeOutWhenFutureObjList.forEach(whenFutureObj ->
-                LOG.warn("requestId [{}] executing thread has reached max-wait-seconds, thread canceled.Execute-item: [{}]", slot.getRequestId(), whenFutureObj.getExecutorName()));
+    public void setPreConditionList(List<Condition> preConditionList) {
+        this.preConditionList = preConditionList;
+    }
 
-        //当配置了errorResume = false,出现interrupted或者!f.get()的情况,将抛出WhenExecuteException
-        if (!condition.isErrorResume()) {
-            if (interrupted[0]) {
-                throw new WhenExecuteException(StrUtil.format("requestId [{}] when execute interrupted. errorResume [false].", slot.getRequestId()));
-            }
+    public List<Condition> getFinallyConditionList() {
+        return finallyConditionList;
+    }
 
-            //循环判断CompletableFuture的返回值,如果异步执行失败,则抛出相应的业务异常
-            for(WhenFutureObj whenFutureObj : allCompletableWhenFutureObjList){
-                if (!whenFutureObj.isSuccess()){
-                    LOG.info(StrUtil.format("requestId [{}] when-executor[{}] execute failed. errorResume [false].", whenFutureObj.getExecutorName(), slot.getRequestId()));
-                    throw whenFutureObj.getEx();
-                }
-            }
-        } else if (interrupted[0]) {
-            //  这里由于配置了errorResume,所以只打印warn日志
-            LOG.warn("requestId [{}] executing when condition timeout , but ignore with errorResume.", slot.getRequestId());
-        }
+    public void setFinallyConditionList(List<Condition> finallyConditionList) {
+        this.finallyConditionList = finallyConditionList;
     }
 }

+ 6 - 20
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java

@@ -8,8 +8,6 @@
 package com.yomahub.liteflow.flow.element;
 
 import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.Map;
 
 import cn.hutool.core.util.BooleanUtil;
 import cn.hutool.core.util.ObjectUtil;
@@ -50,8 +48,6 @@ public class Node implements Executable,Cloneable{
 
 	private String tag;
 
-	private final Map<String, Executable> condNodeMap = new HashMap<>();
-
 	public Node(){
 
 	}
@@ -96,14 +92,6 @@ public class Node implements Executable,Cloneable{
 		this.instance = instance;
 	}
 
-	public Executable getCondNode(String nodeId){
-		return this.condNodeMap.get(nodeId);
-	}
-
-	public void setCondNode(String nodeId, Executable condNode){
-		this.condNodeMap.put(nodeId, condNode);
-	}
-
 	//node的执行主要逻辑
 	//所有的可执行节点,其实最终都会落到node上来,因为chain中包含的也是node
 	@Override
@@ -111,14 +99,12 @@ public class Node implements Executable,Cloneable{
 		if (ObjectUtil.isNull(instance)) {
 			throw new FlowSystemException("there is no instance for node id " + id);
 		}
-		instance.setSlotIndex(slotIndex);
-		Slot<?> slot = DataBus.getSlot(slotIndex);
 
+		Slot slot = DataBus.getSlot(slotIndex);
 		try {
-			//把tag和condNodeMap赋给NodeComponent
-			//这里为什么要这么做?因为tag和condNodeMap从某种意义上来说是属于某个chain本身范围,并非全局的
+			//把线程属性赋值给组件对象
+			instance.setSlotIndex(slotIndex);
 			instance.setTag(tag);
-			instance.setCondNodeMap(condNodeMap);
 
 			LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
 
@@ -126,7 +112,7 @@ public class Node implements Executable,Cloneable{
 			if (instance.isAccess()) {
 				//根据配置判断是否打印执行中的日志
 				if (BooleanUtil.isTrue(liteflowConfig.getPrintExecutionLog())){
-					LOG.info("[{}]:[O]start component[{}] execution",slot.getRequestId(),instance.getClass().getSimpleName());
+					LOG.info("[{}]:[O]start component[{}] execution",slot.getRequestId(), instance.getDisplayName());
 				}
 
 				//这里开始进行重试的逻辑和主逻辑的运行
@@ -135,12 +121,12 @@ public class Node implements Executable,Cloneable{
 				nodeExecutor.execute(instance);
 				//如果组件覆盖了isEnd方法,或者在在逻辑中主要调用了setEnd(true)的话,流程就会立马结束
 				if (instance.isEnd()) {
-					String errorInfo = StrUtil.format("[{}]:component[{}] lead the chain to end", slot.getRequestId(), instance.getClass().getSimpleName());
+					String errorInfo = StrUtil.format("[{}]:[{}] lead the chain to end", slot.getRequestId(), instance.getDisplayName());
 					throw new ChainEndException(errorInfo);
 				}
 			} else {
 				if (BooleanUtil.isTrue(liteflowConfig.getPrintExecutionLog())){
-					LOG.info("[{}]:[X]skip component[{}] execution", slot.getRequestId(), instance.getClass().getSimpleName());
+					LOG.info("[{}]:[X]skip component[{}] execution", slot.getRequestId(), instance.getDisplayName());
 				}
 			}
 		} catch (ChainEndException e){

+ 33 - 20
liteflow-core/src/main/java/com/yomahub/liteflow/flow/condition/Condition.java → liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/Condition.java

@@ -5,24 +5,26 @@
  * @email weenyc31@163.com
  * @Date 2020/4/1
  */
-package com.yomahub.liteflow.flow.condition;
+package com.yomahub.liteflow.flow.element.condition;
 
 import com.yomahub.liteflow.common.LocalDefaultFlowConstant;
+import com.yomahub.liteflow.enums.ExecuteTypeEnum;
 import com.yomahub.liteflow.flow.element.Executable;
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
- * 里面包含了when或者then
+ * Condition的抽象类
  * @author Bryan.Zhang
  */
-public class Condition {
+public abstract class Condition implements Executable{
 
-	//condition 类型 参数:ConditionTypeEnum 包含:then when
-	private ConditionTypeEnum conditionType;
+	private String id;
 
-	private List<Executable> nodeList;
+	//可执行元素的集合
+	private List<Executable> executableList = new ArrayList<>();
 
 	//只在when类型下有效,以区分当when调用链调用失败时是否继续往下执行 默认false不继续执行
 	private boolean errorResume = false;
@@ -32,21 +34,30 @@ public class Condition {
 
 	//只在when类型下有效,为true的话说明在多个并行节点下,任意一个成功,整个when就成功
 	private boolean any = false;
+
 	// when单独的线程池名称
 	private String threadExecutorClass;
 
-	public Condition(List<Executable> nodeList) {
-		this.nodeList = nodeList;
+	@Override
+	public ExecuteTypeEnum getExecuteType() {
+		return ExecuteTypeEnum.CONDITION;
+	}
+
+	@Override
+	public String getExecuteName() {
+		return this.id;
 	}
-	public Condition() {
+
+	public List<Executable> getExecutableList() {
+		return executableList;
 	}
 
-	public List<Executable> getNodeList() {
-		return nodeList;
+	public void setExecutableList(List<Executable> executableList) {
+		this.executableList = executableList;
 	}
 
-	public void setNodeList(List<Executable> nodeList) {
-		this.nodeList = nodeList;
+	public void addExecutable(Executable executable) {
+		this.executableList.add(executable);
 	}
 
 	public boolean isErrorResume() {
@@ -65,13 +76,7 @@ public class Condition {
 		this.group = group;
 	}
 
-	public ConditionTypeEnum getConditionType() {
-		return conditionType;
-	}
-
-	public void setConditionType(ConditionTypeEnum conditionType) {
-		this.conditionType = conditionType;
-	}
+	public abstract ConditionTypeEnum getConditionType();
 
 	public boolean isAny() {
 		return any;
@@ -88,4 +93,12 @@ public class Condition {
 	public void setThreadExecutorClass(String threadExecutorClass) {
 		this.threadExecutorClass = threadExecutorClass;
 	}
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
 }

+ 31 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/FinallyCondition.java

@@ -0,0 +1,31 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.flow.element.condition;
+
+import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.flow.element.Executable;
+
+/**
+ * 前置Condition
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+public class FinallyCondition extends Condition {
+
+	@Override
+	public void execute(Integer slotIndex) throws Exception {
+		for(Executable executableItem : this.getExecutableList()){
+			executableItem.execute(slotIndex);
+		}
+	}
+
+	@Override
+	public ConditionTypeEnum getConditionType() {
+		return ConditionTypeEnum.TYPE_FINALLY;
+	}
+}

+ 31 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/PreCondition.java

@@ -0,0 +1,31 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.flow.element.condition;
+
+import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.flow.element.Executable;
+
+/**
+ * 前置Condition
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+public class PreCondition extends Condition {
+
+	@Override
+	public void execute(Integer slotIndex) throws Exception {
+		for(Executable executableItem : this.getExecutableList()){
+			executableItem.execute(slotIndex);
+		}
+	}
+
+	@Override
+	public ConditionTypeEnum getConditionType() {
+		return ConditionTypeEnum.TYPE_PRE;
+	}
+}

+ 72 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/SwitchCondition.java

@@ -0,0 +1,72 @@
+package com.yomahub.liteflow.flow.element.condition;
+
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.exception.NoSwitchTargetNodeException;
+import com.yomahub.liteflow.exception.SwitchTargetCannotBePreOrFinallyException;
+import com.yomahub.liteflow.exception.SwitchTypeErrorException;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.Node;
+import com.yomahub.liteflow.slot.DataBus;
+import com.yomahub.liteflow.slot.Slot;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 条件Condition
+ * @author Bryan.Zhang
+ * @since 2.8.0
+ */
+public class SwitchCondition extends Condition{
+
+    private final Map<String, Executable> targetMap = new HashMap<>();
+
+    @Override
+    public void execute(Integer slotIndex) throws Exception {
+        if (ListUtil.toList(NodeTypeEnum.SWITCH, NodeTypeEnum.SWITCH_SCRIPT).contains(this.getSwitchNode().getType())){
+            //先执行switch节点
+            this.getSwitchNode().execute(slotIndex);
+
+            //根据switch节点执行出来的结果选择
+            Slot slot = DataBus.getSlot(slotIndex);
+            String targetId = slot.getSwitchResult(this.getSwitchNode().getInstance().getClass().getName());
+            if (StrUtil.isNotBlank(targetId)) {
+                Executable targetExecutor = targetMap.get(targetId);
+                if (ObjectUtil.isNotNull(targetExecutor)) {
+                    //switch的目标不能是Pre节点或者Finally节点
+                    if (targetExecutor instanceof PreCondition || targetExecutor instanceof FinallyCondition){
+                        String errorInfo = StrUtil.format("[{}]:switch component[{}] error, switch target node cannot be pre or finally", slot.getRequestId(), this.getSwitchNode().getInstance().getDisplayName());
+                        throw new SwitchTargetCannotBePreOrFinallyException(errorInfo);
+                    }
+                    targetExecutor.execute(slotIndex);
+                }else{
+                    String errorInfo = StrUtil.format("[{}]:no target node find for the component[{}]", slot.getRequestId(), this.getSwitchNode().getInstance().getDisplayName());
+                    throw new NoSwitchTargetNodeException(errorInfo);
+                }
+            }
+        }else{
+            throw new SwitchTypeErrorException("switch instance must be NodeSwitchComponent");
+        }
+    }
+
+    @Override
+    public ConditionTypeEnum getConditionType() {
+        return ConditionTypeEnum.TYPE_SWITCH;
+    }
+
+    public void addTargetItem(Executable executable){
+        this.targetMap.put(executable.getExecuteName(), executable);
+    }
+
+    public void setSwitchNode(Node switchNode) {
+        this.getExecutableList().add(switchNode);
+    }
+
+    public Node getSwitchNode(){
+        return (Node) this.getExecutableList().get(0);
+    }
+}

+ 33 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ThenCondition.java

@@ -0,0 +1,33 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.flow.element.condition;
+
+import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.flow.element.Executable;
+
+/**
+ * 串行器
+ * @author Bryan.Zhang
+ */
+public class ThenCondition extends Condition {
+	@Override
+	public ConditionTypeEnum getConditionType() {
+		return ConditionTypeEnum.TYPE_THEN;
+	}
+
+	@Override
+	public void execute(Integer slotIndex) throws Exception {
+		for (Executable executableItem : this.getExecutableList()) {
+			//前置和后置组不执行,因为在build的时候会抽出来放在chain里面
+			if (executableItem instanceof PreCondition || executableItem instanceof FinallyCondition){
+				continue;
+			}
+			executableItem.execute(slotIndex);
+		}
+	}
+}

+ 157 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java

@@ -0,0 +1,157 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.flow.element.condition;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.exception.WhenExecuteException;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.parallel.CompletableFutureTimeout;
+import com.yomahub.liteflow.flow.parallel.ParallelSupplier;
+import com.yomahub.liteflow.flow.parallel.WhenFutureObj;
+import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
+import com.yomahub.liteflow.slot.DataBus;
+import com.yomahub.liteflow.slot.Slot;
+import com.yomahub.liteflow.thread.ExecutorHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * 并行器
+ * @author Bryan.Zhang
+ */
+public class WhenCondition extends Condition {
+
+	private final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+
+	@Override
+	public void execute(Integer slotIndex) throws Exception {
+		executeAsyncCondition(slotIndex);
+	}
+
+	@Override
+	public ConditionTypeEnum getConditionType() {
+		return ConditionTypeEnum.TYPE_WHEN;
+	}
+
+	//使用线程池执行when并发流程
+	//这块涉及到挺多的多线程逻辑,所以注释比较详细,看到这里的童鞋可以仔细阅读
+	private void executeAsyncCondition(Integer slotIndex) throws Exception{
+		Slot slot = DataBus.getSlot(slotIndex);
+
+		//此方法其实只会初始化一次Executor,不会每次都会初始化。Executor是唯一的
+		ExecutorService parallelExecutor = ExecutorHelper.loadInstance().buildWhenExecutor(this.getThreadExecutorClass());
+
+		//获得liteflow的参数
+		LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
+
+		//定义是否中断参数
+		//这里为什么要定义成数组呢,因为后面lambda要用到,根据final不能修改引用的原则,这里用了数组对象
+		final boolean[] interrupted = {false};
+
+		//这里主要是做了封装CompletableFuture对象,用lumbda表达式做了很多事情,这句代码要仔细理清
+		//1.先进行过滤,前置和后置组件过滤掉,因为在EL Chain处理的时候已经提出来了
+		//2.过滤isAccess为false的情况,因为不过滤这个的话,如果加上了any,那么isAccess为false那就是最快的了
+		//3.根据condition.getNodeList()的集合进行流处理,用map进行把executable对象转换成List<CompletableFuture<WhenFutureObj>>
+		//4.在转的过程中,套入CompletableFutureTimeout方法进行超时判断,如果超时则用WhenFutureObj.timeOut返回超时的对象
+		//5.第2个参数是主要的本体CompletableFuture,传入了ParallelSupplier和线程池对象
+		List<CompletableFuture<WhenFutureObj>> completableFutureList = this.getExecutableList().stream().filter(executable ->
+				!(executable instanceof PreCondition) && !(executable instanceof FinallyCondition)
+		).filter(executable -> {
+			try {
+				return executable.isAccess(slotIndex);
+			}catch (Exception e){
+				LOG.error("there was an error when executing the when component isAccess",e);
+				return false;
+			}
+		}).map(executable -> CompletableFutureTimeout.completeOnTimeout(
+				WhenFutureObj.timeOut(executable.getExecuteName()),
+				CompletableFuture.supplyAsync(new ParallelSupplier(executable, slotIndex), parallelExecutor),
+				liteflowConfig.getWhenMaxWaitSeconds(),
+				TimeUnit.SECONDS
+		)).collect(Collectors.toList());
+
+
+		CompletableFuture<?> resultCompletableFuture;
+
+		//这里判断执行方式
+		//如果any为false,说明这些异步任务全部执行好或者超时,才返回
+		//如果any为true,说明这些异步任务只要任意一个执行完成,就返回
+		if(this.isAny()){
+			//把这些CompletableFuture通过anyOf合成一个CompletableFuture
+			resultCompletableFuture = CompletableFuture.anyOf(completableFutureList.toArray(new CompletableFuture[]{}));
+		}else{
+			//把这些CompletableFuture通过allOf合成一个CompletableFuture
+			resultCompletableFuture = CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[]{}));
+		}
+
+		try {
+			//进行执行,这句执行完后,就意味着所有的任务要么执行完毕,要么超时返回
+			resultCompletableFuture.get();
+		} catch (InterruptedException | ExecutionException e) {
+			LOG.error("there was an error when executing the CompletableFuture",e);
+			interrupted[0] = true;
+		}
+
+		//拿到已经完成的CompletableFuture
+		//如果any为false,那么所有任务都已经完成
+		//如果any为true,那么这里拿到的是第一个完成的任务
+		//这里过滤和转换一起用lumbda做了
+		List<WhenFutureObj> allCompletableWhenFutureObjList = completableFutureList.stream().filter(f -> {
+			//过滤出已经完成的,没完成的就直接终止
+			if (f.isDone()){
+				return true;
+			}else{
+				f.cancel(true);
+				return false;
+			}
+		}).map(f -> {
+			try {
+				return f.get();
+			} catch (InterruptedException | ExecutionException e) {
+				interrupted[0] = true;
+				return null;
+			}
+		}).collect(Collectors.toList());
+
+		//判断超时,上面已经拿到了所有已经完成的CompletableFuture
+		//那我们只要过滤出超时的CompletableFuture
+		List<WhenFutureObj> timeOutWhenFutureObjList = allCompletableWhenFutureObjList.stream().filter(WhenFutureObj::isTimeout).collect(Collectors.toList());
+
+		//输出超时信息
+		timeOutWhenFutureObjList.forEach(whenFutureObj ->
+				LOG.warn("requestId [{}] executing thread has reached max-wait-seconds, thread canceled.Execute-item: [{}]", slot.getRequestId(), whenFutureObj.getExecutorName()));
+
+		//当配置了errorResume = false,出现interrupted或者!f.get()的情况,将抛出WhenExecuteException
+		if (!this.isErrorResume()) {
+			if (interrupted[0]) {
+				throw new WhenExecuteException(StrUtil.format("requestId [{}] when execute interrupted. errorResume [false].", slot.getRequestId()));
+			}
+
+			//循环判断CompletableFuture的返回值,如果异步执行失败,则抛出相应的业务异常
+			for(WhenFutureObj whenFutureObj : allCompletableWhenFutureObjList){
+				if (!whenFutureObj.isSuccess()){
+					LOG.info(StrUtil.format("requestId [{}] when-executor[{}] execute failed. errorResume [false].",slot.getRequestId(), whenFutureObj.getExecutorName()));
+					throw whenFutureObj.getEx();
+				}
+			}
+		} else if (interrupted[0]) {
+			//  这里由于配置了errorResume,所以只打印warn日志
+			LOG.warn("requestId [{}] executing when condition timeout , but ignore with errorResume.", slot.getRequestId());
+		}
+	}
+}

+ 1 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/flow/executor/NodeExecutor.java

@@ -50,7 +50,7 @@ public abstract class NodeExecutor {
     //执行重试逻辑 - 子类通过实现该方法进行重试逻辑的控制
     protected void retry(NodeComponent instance, int currentRetryCount) throws Exception {
         Slot slot = DataBus.getSlot(instance.getSlotIndex());
-        LOG.info("[{}]:component[{}] performs {} retry", slot.getRequestId(), instance.getNodeId(), currentRetryCount + 1);
+        LOG.info("[{}]:component[{}] performs {} retry", slot.getRequestId(),instance.getDisplayName(), currentRetryCount + 1);
         //执行业务逻辑的主要入口
         instance.execute();
     }

+ 16 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/id/DefaultRequestIdGenerator.java

@@ -0,0 +1,16 @@
+package com.yomahub.liteflow.flow.id;
+
+import cn.hutool.core.util.IdUtil;
+
+/**
+ * 默认 Id 生成器
+ *
+ * @author tangkc
+ */
+public class DefaultRequestIdGenerator implements RequestIdGenerator {
+
+    @Override
+    public String generate() {
+        return IdUtil.fastSimpleUUID();
+    }
+}

+ 59 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/id/IdGeneratorHelper.java

@@ -0,0 +1,59 @@
+package com.yomahub.liteflow.flow.id;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.exception.RequestIdGeneratorException;
+import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
+import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
+
+import java.util.Objects;
+
+/**
+ * Id 生成器帮助器
+ *
+ * @author tangkc
+ */
+public class IdGeneratorHelper {
+
+    private static RequestIdGenerator requestIdGenerator;
+
+    private volatile static IdGeneratorHelper INSTANCE;
+
+    private IdGeneratorHelper() {
+
+    }
+
+    public static IdGeneratorHelper getInstance() {
+        if (Objects.isNull(INSTANCE)) {
+            //这里加同步锁是为了避免启动后第一次多并发获取requestId而造成重复初始化的场景
+            //并非每次都会执行这个同步锁,所以不存在性能问题
+            synchronized (IdGeneratorHelper.class) {
+                if (Objects.isNull(INSTANCE)) {
+                    INSTANCE = new IdGeneratorHelper();
+                    LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
+                    String requestIdGeneratorClass = liteflowConfig.getRequestIdGeneratorClass();
+                    if (StrUtil.isBlank(requestIdGeneratorClass)) {
+                        requestIdGenerator = new DefaultRequestIdGenerator();
+                    }
+                    try {
+                        Class<RequestIdGenerator> idGenerateClass = (Class<RequestIdGenerator>) Class.forName(requestIdGeneratorClass);
+                        requestIdGenerator = ContextAwareHolder.loadContextAware().registerBean(idGenerateClass);
+                    } catch (Exception e) {
+                        throw new RequestIdGeneratorException(e.getMessage());
+                    }
+                }
+            }
+        }
+
+        return INSTANCE;
+    }
+
+    public String generate() {
+        return requestIdGenerator.generate();
+    }
+
+    public void clear(){
+        INSTANCE = null;
+    }
+
+}

+ 17 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/id/RequestIdGenerator.java

@@ -0,0 +1,17 @@
+package com.yomahub.liteflow.flow.id;
+
+/**
+ * Id 生成接口
+ *
+ * @author tangkc
+ */
+public interface RequestIdGenerator {
+
+    /**
+     * 获取唯一 id
+     *
+     * @return 返回唯一 id
+     */
+    String generate();
+
+}

+ 0 - 6
liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/CompletableFutureTimeout.java

@@ -59,10 +59,4 @@ public class CompletableFutureTimeout {
         final CompletableFuture<T> timeoutFuture = timeoutAfter(timeout, unit);
         return future.applyToEither(timeoutFuture, Function.identity()).exceptionally((throwable) -> t);
     }
-
-    //哪个先完成 就apply哪一个结果 这是一个关键的API,不设置默认值,超时后抛出异常
-    public static <T> CompletableFuture<T> orTimeout(T t, CompletableFuture<T> future, long timeout, TimeUnit unit) {
-        final CompletableFuture<T> timeoutFuture = timeoutAfter(timeout, unit);
-        return future.applyToEither(timeoutFuture, Function.identity()).exceptionally((throwable) -> t);
-    }
 }

+ 3 - 2
liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java

@@ -7,8 +7,9 @@
  */
 package com.yomahub.liteflow.monitor;
 
-import com.yomahub.liteflow.slot.DataBus;
+import cn.hutool.core.util.BooleanUtil;
 import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.util.BoundedPriorityBlockingQueue;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -40,7 +41,7 @@ public class MonitorBus {
 	public MonitorBus(LiteflowConfig liteflowConfig) {
 		this.liteflowConfig = liteflowConfig;
 
-		if(liteflowConfig.getEnableLog()){
+		if(BooleanUtil.isTrue(liteflowConfig.getEnableLog())){
 			this.printLogScheduler.scheduleAtFixedRate(new MonitorTimeTask(this), liteflowConfig.getDelay(), liteflowConfig.getPeriod(), TimeUnit.MILLISECONDS);
 		}
 	}

+ 20 - 159
liteflow-core/src/main/java/com/yomahub/liteflow/parser/JsonFlowParser.java

@@ -1,25 +1,20 @@
 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.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
-import com.alibaba.fastjson.parser.Feature;
 import com.yomahub.liteflow.builder.LiteFlowChainBuilder;
-import com.yomahub.liteflow.builder.LiteFlowConditionBuilder;
-import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
+import com.yomahub.liteflow.builder.prop.ChainPropBean;
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
-import com.yomahub.liteflow.enums.NodeTypeEnum;
-import com.yomahub.liteflow.exception.EmptyConditionValueException;
-import com.yomahub.liteflow.exception.NodeTypeNotSupportException;
-import com.yomahub.liteflow.exception.NotSupportConditionException;
-import com.yomahub.liteflow.flow.FlowBus;
-import com.yomahub.liteflow.spi.holder.ContextCmpInitHolder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.util.*;
+import com.yomahub.liteflow.parser.base.BaseJsonFlowParser;
+import com.yomahub.liteflow.parser.helper.ParserHelper;
+
+import static com.yomahub.liteflow.common.ChainConstant.ANY;
+import static com.yomahub.liteflow.common.ChainConstant.CONDITION;
+import static com.yomahub.liteflow.common.ChainConstant.ERROR_RESUME;
+import static com.yomahub.liteflow.common.ChainConstant.GROUP;
+import static com.yomahub.liteflow.common.ChainConstant.NAME;
+import static com.yomahub.liteflow.common.ChainConstant.THREAD_EXECUTOR_CLASS;
+import static com.yomahub.liteflow.common.ChainConstant.TYPE;
+import static com.yomahub.liteflow.common.ChainConstant.VALUE;
 
 /**
  * Json格式解析器
@@ -27,148 +22,14 @@ import java.util.*;
  * @author guodongqing
  * @since 2.5.0
  */
-public abstract class JsonFlowParser implements FlowParser {
+public abstract class JsonFlowParser extends BaseJsonFlowParser {
 
-    private final Logger LOG = LoggerFactory.getLogger(JsonFlowParser.class);
+	/**
+	 * 解析一个chain的过程
+	 */
+	@Override
+	public void parseOneChain(JSONObject chainObject) {
+		ParserHelper.parseOneChain(chainObject);
+	}
 
-    public void parse(String content) throws Exception {
-        parse(ListUtil.toList(content));
-    }
-
-    @Override
-    public void parse(List<String> contentList) throws Exception {
-        if (CollectionUtil.isEmpty(contentList)) {
-            return;
-        }
-
-        List<JSONObject> jsonObjectList = ListUtil.toList();
-        for (String content : contentList) {
-            //把字符串原生转换为json对象,如果不加第二个参数OrderedField,会无序
-            JSONObject flowJsonObject = JSONObject.parseObject(content, Feature.OrderedField);
-            jsonObjectList.add(flowJsonObject);
-        }
-
-        parseJsonObject(jsonObjectList);
-    }
-
-    //json格式,解析过程
-    public void parseJsonObject(List<JSONObject> flowJsonObjectList) throws Exception {
-        //在相应的环境下进行节点的初始化工作
-        //在spring体系下会获得spring扫描后的节点,接入元数据
-        //在非spring体系下是一个空实现,等于不做此步骤
-        ContextCmpInitHolder.loadContextCmpInit().initCmp();
-
-        //先在元数据里放上chain
-        //先放有一个好处,可以在parse的时候先映射到FlowBus的chainMap,然后再去解析
-        //这样就不用去像之前的版本那样回归调用
-        //同时也解决了不能循环依赖的问题
-        flowJsonObjectList.forEach(jsonObject -> {
-            // 解析chain节点
-            JSONArray chainArray = jsonObject.getJSONObject("flow").getJSONArray("chain");
-
-            //先在元数据里放上chain
-            chainArray.forEach(o -> {
-                JSONObject innerJsonObject = (JSONObject)o;
-                FlowBus.addChain(innerJsonObject.getString("name"));
-            });
-        });
-
-        for (JSONObject flowJsonObject : flowJsonObjectList) {
-            // 当存在<nodes>节点定义时,解析node节点
-            if (flowJsonObject.getJSONObject("flow").containsKey("nodes")){
-                JSONArray nodeArrayList = flowJsonObject.getJSONObject("flow").getJSONObject("nodes").getJSONArray("node");
-                String id, name, clazz, script, type, file;
-                for (int i = 0; i < nodeArrayList.size(); i++) {
-                    JSONObject nodeObject = nodeArrayList.getJSONObject(i);
-                    id = nodeObject.getString("id");
-                    name = nodeObject.getString("name");
-                    clazz = nodeObject.getString("class");
-                    type = nodeObject.getString("type");
-                    script = nodeObject.getString("value");
-                    file = nodeObject.getString("file");
-
-                    //初始化type
-                    if (StrUtil.isBlank(type)){
-                        type = NodeTypeEnum.COMMON.getCode();
-                    }
-
-                    //检查nodeType是不是规定的类型
-                    NodeTypeEnum nodeTypeEnum = NodeTypeEnum.getEnumByCode(type);
-                    if (ObjectUtil.isNull(nodeTypeEnum)){
-                        throw new NodeTypeNotSupportException(StrUtil.format("type [{}] is not support", type));
-                    }
-
-                    //进行node的build过程
-                    LiteFlowNodeBuilder.createNode().setId(id)
-                            .setName(name)
-                            .setClazz(clazz)
-                            .setType(nodeTypeEnum)
-                            .setScript(script)
-                            .setFile(file)
-                            .build();
-                }
-            }
-
-            //解析每一个chain
-            JSONArray chainArray = flowJsonObject.getJSONObject("flow").getJSONArray("chain");
-            chainArray.forEach(o -> {
-                JSONObject jsonObject = (JSONObject)o;
-                parseOneChain(jsonObject);
-            });
-        }
-    }
-
-    /**
-     * 解析一个chain的过程
-     */
-    private void parseOneChain(JSONObject chainObject){
-        String condValueStr;
-        ConditionTypeEnum conditionType;
-        String group;
-        String errorResume;
-        String any;
-        String threadExecutorClass;
-
-        //构建chainBuilder
-        String chainName = chainObject.getString("name");
-        LiteFlowChainBuilder chainBuilder = LiteFlowChainBuilder.createChain().setChainName(chainName);
-
-        for (Object o : chainObject.getJSONArray("condition")) {
-            JSONObject condObject = (JSONObject) o;
-            conditionType = ConditionTypeEnum.getEnumByCode(condObject.getString("type"));
-            condValueStr = condObject.getString("value");
-            errorResume = condObject.getString("errorResume");
-            group = condObject.getString("group");
-            any = condObject.getString("any");
-            threadExecutorClass = condObject.getString("threadExecutorClass");
-
-            if (ObjectUtil.isNull(conditionType)){
-                throw new NotSupportConditionException("ConditionType is not supported");
-            }
-
-            if (StrUtil.isBlank(condValueStr)) {
-                throw new EmptyConditionValueException("Condition value cannot be empty");
-            }
-
-
-            //如果是when类型的话,有特殊化参数要设置,只针对于when的
-            if (conditionType.equals(ConditionTypeEnum.TYPE_WHEN)){
-                chainBuilder.setCondition(
-                        LiteFlowConditionBuilder.createWhenCondition()
-                                .setErrorResume(errorResume)
-                                .setGroup(group)
-                                .setAny(any)
-                                .setThreadExecutorClass(threadExecutorClass)
-                                .setValue(condValueStr)
-                                .build()
-                ).build();
-            }else{
-                chainBuilder.setCondition(
-                        LiteFlowConditionBuilder.createCondition(conditionType)
-                                .setValue(condValueStr)
-                                .build()
-                ).build();
-            }
-        }
-    }
 }

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/parser/LocalXmlFlowParser.java

@@ -17,6 +17,7 @@ import java.util.List;
  */
 public class LocalXmlFlowParser extends XmlFlowParser{
 
+	@Override
 	public void parseMain(List<String> pathList) throws Exception {
 		List<String> contentList = PathContentParserHolder.loadContextAware().parseContent(pathList);
 		parse(contentList);

+ 12 - 150
liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java

@@ -1,161 +1,23 @@
 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.builder.LiteFlowChainBuilder;
-import com.yomahub.liteflow.builder.LiteFlowConditionBuilder;
-import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
-import com.yomahub.liteflow.enums.ConditionTypeEnum;
-import com.yomahub.liteflow.enums.NodeTypeEnum;
-import com.yomahub.liteflow.exception.*;
-import com.yomahub.liteflow.flow.FlowBus;
-import com.yomahub.liteflow.spi.holder.ContextCmpInitHolder;
-import org.dom4j.Document;
-import org.dom4j.DocumentHelper;
+import com.yomahub.liteflow.parser.base.BaseXmlFlowParser;
+import com.yomahub.liteflow.parser.helper.ParserHelper;
 import org.dom4j.Element;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.util.Iterator;
-import java.util.List;
+
+;
 
 /**
  * xml形式的解析器
+ *
  * @author Bryan.Zhang
  */
-public abstract class XmlFlowParser implements FlowParser {
-
-    private final Logger LOG = LoggerFactory.getLogger(XmlFlowParser.class);
-
-    public void parse(String content) throws Exception {
-        parse(ListUtil.toList(content));
-    }
-
-    public void parse(List<String> contentList) throws Exception {
-        if (CollectionUtil.isEmpty(contentList)) {
-            return;
-        }
-        List<Document> documentList = ListUtil.toList();
-        for (String content : contentList) {
-            Document document = DocumentHelper.parseText(content);
-            documentList.add(document);
-        }
-        parseDocument(documentList);
-    }
-
-    //xml形式的主要解析过程
-    public void parseDocument(List<Document> documentList) throws Exception {
-        //在相应的环境下进行节点的初始化工作
-        //在spring体系下会获得spring扫描后的节点,接入元数据
-        //在非spring体系下是一个空实现,等于不做此步骤
-        ContextCmpInitHolder.loadContextCmpInit().initCmp();
-
-        //先在元数据里放上chain
-        //先放有一个好处,可以在parse的时候先映射到FlowBus的chainMap,然后再去解析
-        //这样就不用去像之前的版本那样回归调用
-        //同时也解决了不能循环依赖的问题
-        documentList.forEach(document -> {
-            // 解析chain节点
-            List<Element> chainList = document.getRootElement().elements("chain");
-
-            //先在元数据里放上chain
-            chainList.forEach(e -> FlowBus.addChain(e.attributeValue("name")));
-        });
-
-        for (Document document : documentList) {
-            Element rootElement = document.getRootElement();
-            Element nodesElement = rootElement.element("nodes");
-            // 当存在<nodes>节点定义时,解析node节点
-            if (ObjectUtil.isNotNull(nodesElement)){
-                List<Element> nodeList = nodesElement.elements("node");
-                String id, name, clazz, type, script, file;
-                for (Element e : nodeList) {
-                    id = e.attributeValue("id");
-                    name = e.attributeValue("name");
-                    clazz = e.attributeValue("class");
-                    type = e.attributeValue("type");
-                    script = e.getTextTrim();
-                    file = e.attributeValue("file");
-
-                    //初始化type
-                    if (StrUtil.isBlank(type)){
-                        type = NodeTypeEnum.COMMON.getCode();
-                    }
-
-                    //检查nodeType是不是规定的类型
-                    NodeTypeEnum nodeTypeEnum = NodeTypeEnum.getEnumByCode(type);
-                    if (ObjectUtil.isNull(nodeTypeEnum)){
-                        throw new NodeTypeNotSupportException(StrUtil.format("type [{}] is not support", type));
-                    }
-
-                    //进行node的build过程
-                    LiteFlowNodeBuilder.createNode().setId(id)
-                            .setName(name)
-                            .setClazz(clazz)
-                            .setType(nodeTypeEnum)
-                            .setScript(script)
-                            .setFile(file)
-                            .build();
-                }
-            }
-
-            //解析每一个chain
-            List<Element> chainList = rootElement.elements("chain");
-            chainList.forEach(this::parseOneChain);
-        }
-    }
-
-    /**
-     * 解析一个chain的过程
-     */
-    private void parseOneChain(Element e) {
-        String condValueStr;
-        String group;
-        String errorResume;
-        String any;
-        String threadExecutorClass;
-        ConditionTypeEnum conditionType;
-
-        //构建chainBuilder
-        String chainName = e.attributeValue("name");
-        LiteFlowChainBuilder chainBuilder = LiteFlowChainBuilder.createChain().setChainName(chainName);
-
-        for (Iterator<Element> it = e.elementIterator(); it.hasNext(); ) {
-            Element condE = it.next();
-            conditionType = ConditionTypeEnum.getEnumByCode(condE.getName());
-            condValueStr = condE.attributeValue("value");
-            errorResume = condE.attributeValue("errorResume");
-            group = condE.attributeValue("group");
-            any = condE.attributeValue("any");
-            threadExecutorClass = condE.attributeValue("threadExecutorClass");
-
-            if (ObjectUtil.isNull(conditionType)){
-                throw new NotSupportConditionException("ConditionType is not supported");
-            }
+public abstract class XmlFlowParser extends BaseXmlFlowParser {
 
-            if (StrUtil.isBlank(condValueStr)) {
-                throw new EmptyConditionValueException("Condition value cannot be empty");
-            }
+	/**
+	 * 解析一个chain的过程
+	 */
+	public void parseOneChain(Element e) {
+		ParserHelper.parseOneChain(e);
+	}
 
-            //如果是when类型的话,有特殊化参数要设置,只针对于when的
-            if (conditionType.equals(ConditionTypeEnum.TYPE_WHEN)){
-                chainBuilder.setCondition(
-                        LiteFlowConditionBuilder.createWhenCondition()
-                                .setErrorResume(errorResume)
-                                .setGroup(group)
-                                .setAny(any)
-                                .setThreadExecutorClass(threadExecutorClass)
-                                .setValue(condValueStr)
-                                .build()
-                ).build();
-            }else{
-                chainBuilder.setCondition(
-                        LiteFlowConditionBuilder.createCondition(conditionType)
-                                .setValue(condValueStr)
-                                .build()
-                ).build();
-            }
-        }
-    }
 }

+ 8 - 33
liteflow-core/src/main/java/com/yomahub/liteflow/parser/YmlFlowParser.java

@@ -1,47 +1,22 @@
 package com.yomahub.liteflow.parser;
 
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.collection.ListUtil;
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.yaml.snakeyaml.Yaml;
-
-import java.util.List;
-import java.util.Map;
+import com.yomahub.liteflow.parser.base.BaseYmlFlowParser;
+import com.yomahub.liteflow.parser.helper.ParserHelper;
 
 /**
  * Yml格式解析器,转换为json格式进行解析
  * @author guodongqing
  * @since 2.5.0
  */
-public abstract class YmlFlowParser extends JsonFlowParser{
-
-    private final Logger LOG = LoggerFactory.getLogger(YmlFlowParser.class);
-
-    public void parse(String content) throws Exception{
-        parse(ListUtil.toList(content));
-    }
+public abstract class YmlFlowParser extends BaseYmlFlowParser {
 
+    /**
+     * 解析一个chain的过程
+     */
     @Override
-    public void parse(List<String> contentList) throws Exception {
-        if (CollectionUtil.isEmpty(contentList)) {
-            return;
-        }
-
-        List<JSONObject> jsonObjectList = ListUtil.toList();
-        for (String content : contentList){
-            JSONObject ruleObject = convertToJson(content);
-            jsonObjectList.add(ruleObject);
-        }
-
-        super.parseJsonObject(jsonObjectList);
+    public void parseOneChain(JSONObject chainObject) {
+        ParserHelper.parseOneChain(chainObject);
     }
 
-    protected JSONObject convertToJson(String yamlString) {
-        Yaml yaml= new Yaml();
-        Map<String, Object> map = yaml.load(yamlString);
-        return JSON.parseObject(JSON.toJSONString(map));
-    }
 }

+ 8 - 48
liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperJsonFlowParser.java

@@ -1,63 +1,23 @@
 package com.yomahub.liteflow.parser;
 
-import cn.hutool.core.util.StrUtil;
-import com.yomahub.liteflow.exception.ParseException;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.framework.recipes.cache.NodeCache;
-import org.apache.curator.retry.RetryNTimes;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.text.MessageFormat;
-import java.util.List;
+import com.alibaba.fastjson.JSONObject;
+import com.yomahub.liteflow.parser.base.BaseZookeeperJsonFlowParser;
+import com.yomahub.liteflow.parser.helper.ParserHelper;
 
 /**
  * 基于zk方式的json形式的解析器
  * @author guodongqing
  * @since 2.5.0
  */
-public class ZookeeperJsonFlowParser extends JsonFlowParser{
-
-    private static final Logger LOG = LoggerFactory.getLogger(ZookeeperJsonFlowParser.class);
-
-    private final String nodePath;
+public class ZookeeperJsonFlowParser extends BaseZookeeperJsonFlowParser {
 
     public ZookeeperJsonFlowParser(String node) {
-        nodePath = node;
+        super(node);
     }
 
     @Override
-    public void parseMain(List<String> pathList) throws Exception {
-        //zk不允许有多个path
-        String path = pathList.get(0);
-        CuratorFramework client = CuratorFrameworkFactory.newClient(
-                path,
-                new RetryNTimes(10, 5000)
-        );
-        client.start();
-
-        if (client.checkExists().forPath(nodePath) == null) {
-            client.create().creatingParentsIfNeeded().forPath(nodePath, "".getBytes());
-        }
-
-        String content = new String(client.getData().forPath(nodePath));
-
-
-        if (StrUtil.isBlank(content)) {
-            String error = MessageFormat.format("the node[{0}] value is empty", nodePath);
-            throw new ParseException(error);
-        }
-        parse(content);
-
-
-        final NodeCache cache = new NodeCache(client,nodePath);
-        cache.start();
-
-        cache.getListenable().addListener(() -> {
-            String content1 = new String(cache.getCurrentData().getData());
-            LOG.info("stating load flow config....");
-            parse(content1);
-        });
+    public void parseOneChain(JSONObject chainObject) {
+        ParserHelper.parseOneChain(chainObject);
     }
+
 }

+ 7 - 51
liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperXmlFlowParser.java

@@ -1,65 +1,21 @@
 package com.yomahub.liteflow.parser;
 
-import java.text.MessageFormat;
-import java.util.List;
-
-import cn.hutool.core.util.StrUtil;
-
-import com.yomahub.liteflow.flow.FlowBus;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.framework.recipes.cache.NodeCache;
-import org.apache.curator.retry.RetryNTimes;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.yomahub.liteflow.exception.ParseException;
+import com.yomahub.liteflow.parser.base.BaseZookeeperXmlFlowParser;
+import com.yomahub.liteflow.parser.helper.ParserHelper;
+import org.dom4j.Element;
 
 /**
  * 基于zk方式的xml形式的解析器
  * @author Bryan.Zhang
  */
-public class ZookeeperXmlFlowParser extends XmlFlowParser{
-
-	private static final Logger LOG = LoggerFactory.getLogger(ZookeeperXmlFlowParser.class);
-
-	private final String nodePath;
+public class ZookeeperXmlFlowParser extends BaseZookeeperXmlFlowParser {
 
 	public ZookeeperXmlFlowParser(String node) {
-		nodePath = node;
+		super(node);
 	}
 
 	@Override
-	public void parseMain(List<String> pathList) throws Exception {
-        //zk不允许有多个path
-        String path = pathList.get(0);
-		CuratorFramework client = CuratorFrameworkFactory.newClient(
-				path,
-                new RetryNTimes(10, 5000)
-        );
-        client.start();
-
-        if (client.checkExists().forPath(nodePath) == null) {
-        	client.create().creatingParentsIfNeeded().forPath(nodePath, "".getBytes());
-        }
-
-        String content = new String(client.getData().forPath(nodePath));
-
-
-        if (StrUtil.isBlank(content)) {
-        	String error = MessageFormat.format("the node[{0}] value is empty", nodePath);
-        	throw new ParseException(error);
-        }
-        parse(content);
-
-
-        final NodeCache cache = new NodeCache(client,nodePath);
-        cache.start();
-
-        cache.getListenable().addListener(() -> {
-            String content1 = new String(cache.getCurrentData().getData());
-            LOG.info("stating load flow config....");
-            parse(content1);
-        });
+	public void parseOneChain(Element chain) {
+		ParserHelper.parseOneChain(chain);
 	}
 }

+ 12 - 58
liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperYmlFlowParser.java

@@ -1,68 +1,22 @@
 package com.yomahub.liteflow.parser;
 
-import cn.hutool.core.collection.ListUtil;
-import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONObject;
-import com.yomahub.liteflow.exception.ParseException;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.framework.recipes.cache.NodeCache;
-import org.apache.curator.retry.RetryNTimes;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.text.MessageFormat;
-import java.util.List;
+import com.yomahub.liteflow.parser.base.BaseZookeeperYmlFlowParser;
+import com.yomahub.liteflow.parser.helper.ParserHelper;
 
 /**
  * 基于zk方式的yml形式的解析器
+ *
  * @author guodongqing
  * @since 2.5.0
  */
-public class ZookeeperYmlFlowParser extends YmlFlowParser{
-
-    private static final Logger LOG = LoggerFactory.getLogger(ZookeeperYmlFlowParser.class);
-
-    private final String nodePath;
-
-    public ZookeeperYmlFlowParser(String node) {
-        nodePath = node;
-    }
-
-    @Override
-    public void parseMain(List<String> pathList) throws Exception {
-        //zk不允许有多个path
-        String path = pathList.get(0);
-        CuratorFramework client = CuratorFrameworkFactory.newClient(
-                path,
-                new RetryNTimes(10, 5000)
-        );
-        client.start();
-
-        if (client.checkExists().forPath(nodePath) == null) {
-            client.create().creatingParentsIfNeeded().forPath(nodePath, "".getBytes());
-        }
-
-        String content = new String(client.getData().forPath(nodePath));
-
-        if (StrUtil.isBlank(content)) {
-            String error = MessageFormat.format("the node[{0}] value is empty", nodePath);
-            throw new ParseException(error);
-        }
-
-        JSONObject ruleObject = convertToJson(content);
-
-        parse(ruleObject.toJSONString());
-
-
-        final NodeCache cache = new NodeCache(client,nodePath);
-        cache.start();
-
-        cache.getListenable().addListener(() -> {
-            String content1 = new String(cache.getCurrentData().getData());
-            LOG.info("stating load flow config....");
-            JSONObject ruleObject1 = convertToJson(content1);
-            parse(ruleObject1.toJSONString());
-        });
-    }
+public class ZookeeperYmlFlowParser extends BaseZookeeperYmlFlowParser {
+	public ZookeeperYmlFlowParser(String node) {
+		super(node);
+	}
+
+	@Override
+	public void parseOneChain(JSONObject chain) {
+		ParserHelper.parseOneChain(chain);
+	}
 }

+ 49 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseJsonFlowParser.java

@@ -0,0 +1,49 @@
+package com.yomahub.liteflow.parser.base;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.collection.ListUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.parser.Feature;
+import com.yomahub.liteflow.parser.helper.ParserHelper;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+
+/**
+ * 基类,用于存放 JsonFlowParser 通用方法
+ *
+ * @author tangkc
+ */
+public abstract class BaseJsonFlowParser implements FlowParser {
+
+	private final Set<String> CHAIN_NAME_SET = new CopyOnWriteArraySet<>();
+
+	public void parse(String content) throws Exception {
+		parse(ListUtil.toList(content));
+	}
+
+	@Override
+	public void parse(List<String> contentList) throws Exception {
+		if (CollectionUtil.isEmpty(contentList)) {
+			return;
+		}
+
+		List<JSONObject> jsonObjectList = ListUtil.toList();
+		for (String content : contentList) {
+			//把字符串原生转换为json对象,如果不加第二个参数OrderedField,会无序
+			JSONObject flowJsonObject = JSONObject.parseObject(content, Feature.OrderedField);
+			jsonObjectList.add(flowJsonObject);
+		}
+		ParserHelper.parseJsonObject(jsonObjectList, CHAIN_NAME_SET, this::parseOneChain);
+	}
+
+	/**
+	 * 解析一个chain的过程
+	 *
+	 * @param chainObject chain 节点
+	 */
+	public abstract void parseOneChain(JSONObject chainObject);
+
+}

+ 50 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseXmlFlowParser.java

@@ -0,0 +1,50 @@
+package com.yomahub.liteflow.parser.base;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.collection.ListUtil;
+import com.yomahub.liteflow.parser.helper.ParserHelper;
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
+
+
+/**
+ * 基类,用于存放 XmlFlowParser 通用方法
+ *
+ * @author tangkc
+ */
+public abstract class BaseXmlFlowParser implements FlowParser {
+	private final Set<String> CHAIN_NAME_SET = new HashSet<>();
+
+	public void parse(String content) throws Exception {
+		parse(ListUtil.toList(content));
+	}
+
+	@Override
+	public void parse(List<String> contentList) throws Exception {
+		if (CollectionUtil.isEmpty(contentList)) {
+			return;
+		}
+		List<Document> documentList = ListUtil.toList();
+		for (String content : contentList) {
+			Document document = DocumentHelper.parseText(content);
+			documentList.add(document);
+		}
+
+		Consumer<Element> parseOneChainConsumer = this::parseOneChain;
+		ParserHelper.parseDocument(documentList, CHAIN_NAME_SET, parseOneChainConsumer);
+	}
+
+	/**
+	 * 解析一个 chain 的过程
+	 *
+	 * @param chain chain
+	 */
+	public abstract void parseOneChain(Element chain);
+
+}

+ 57 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseYmlFlowParser.java

@@ -0,0 +1,57 @@
+package com.yomahub.liteflow.parser.base;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.collection.ListUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.yomahub.liteflow.parser.helper.ParserHelper;
+import org.yaml.snakeyaml.Yaml;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+
+/**
+ * 基类,用于存放 YmlFlowParser 通用方法
+ *
+ * @author tangkc
+ */
+public abstract class BaseYmlFlowParser implements FlowParser {
+
+	private final Set<String> CHAIN_NAME_SET = new HashSet<>();
+
+	public void parse(String content) throws Exception{
+		parse(ListUtil.toList(content));
+	}
+
+	@Override
+	public void parse(List<String> contentList) throws Exception {
+		if (CollectionUtil.isEmpty(contentList)) {
+			return;
+		}
+
+		List<JSONObject> jsonObjectList = ListUtil.toList();
+		for (String content : contentList){
+			JSONObject ruleObject = convertToJson(content);
+			jsonObjectList.add(ruleObject);
+		}
+
+		Consumer<JSONObject> parseOneChainConsumer = this::parseOneChain;
+		ParserHelper.parseJsonObject(jsonObjectList, CHAIN_NAME_SET,parseOneChainConsumer);
+	}
+
+	protected JSONObject convertToJson(String yamlString) {
+		Yaml yaml= new Yaml();
+		Map<String, Object> map = yaml.load(yamlString);
+		return JSON.parseObject(JSON.toJSONString(map));
+	}
+
+	/**
+	 * 解析一个 chain 的过程
+	 *
+	 * @param chain chain
+	 */
+	public abstract void parseOneChain(JSONObject chain);
+}

+ 58 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseZookeeperJsonFlowParser.java

@@ -0,0 +1,58 @@
+package com.yomahub.liteflow.parser.base;
+
+import com.alibaba.fastjson.JSONObject;
+import com.yomahub.liteflow.parser.ZookeeperJsonFlowParser;
+import com.yomahub.liteflow.parser.helper.ZkParserHelper;
+import org.apache.curator.framework.CuratorFramework;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * 基类,用于存放 ZookeeperJsonFlowParser 通用方法
+ *
+ * @author tangkc
+ */
+public abstract class BaseZookeeperJsonFlowParser extends BaseJsonFlowParser {
+
+	private static final Logger LOG = LoggerFactory.getLogger(ZookeeperJsonFlowParser.class);
+
+	private final String nodePath;
+
+	private final ZkParserHelper zkParserHelper;
+
+	public BaseZookeeperJsonFlowParser(String node) {
+		nodePath = node;
+		Consumer<String> parseConsumer = t -> {
+			try {
+				parse(t);
+			} catch (Exception e) {
+				throw new RuntimeException(e);
+			}
+		};
+		zkParserHelper = new ZkParserHelper(nodePath, parseConsumer);
+	}
+
+	@Override
+	public void parseMain(List<String> pathList) throws Exception {
+		CuratorFramework client = zkParserHelper.getZkCuratorFramework(pathList);
+
+		String content = new String(client.getData().forPath(nodePath));
+
+		zkParserHelper.checkContent(content);
+
+		parse(content);
+
+		zkParserHelper.listenZkNode(client);
+	}
+
+	/**
+	 * 解析一个chain的过程
+	 *
+	 * @param chainObject chain 节点
+	 */
+	@Override
+	public abstract void parseOneChain(JSONObject chainObject);
+}

+ 58 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/parser/base/BaseZookeeperXmlFlowParser.java

@@ -0,0 +1,58 @@
+package com.yomahub.liteflow.parser.base;
+
+import com.yomahub.liteflow.parser.ZookeeperXmlFlowParser;
+import com.yomahub.liteflow.parser.helper.ZkParserHelper;
+import org.apache.curator.framework.CuratorFramework;
+import org.dom4j.Element;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * 基类,用于存放 ZookeeperXmlFlowELParser 通用方法
+ *
+ * @author tangkc
+ */
+public abstract class BaseZookeeperXmlFlowParser extends BaseXmlFlowParser {
+
+	private static final Logger LOG = LoggerFactory.getLogger(ZookeeperXmlFlowParser.class);
+
+	private final String nodePath;
+
+	private final ZkParserHelper zkParserHelper;
+
+	public BaseZookeeperXmlFlowParser(String node) {
+		nodePath = node;
+		Consumer<String> parseConsumer = t -> {
+			try {
+				parse(t);
+			} catch (Exception e) {
+				throw new RuntimeException(e);
+			}
+		};
+		zkParserHelper = new ZkParserHelper(nodePath, parseConsumer);
+	}
+
+	@Override
+	public void parseMain(List<String> pathList) throws Exception {
+		CuratorFramework client = zkParserHelper.getZkCuratorFramework(pathList);
+
+		String content = new String(client.getData().forPath(nodePath));
+
+		zkParserHelper.checkContent(content);
+
+		parse(content);
+
+		zkParserHelper.listenZkNode(client);
+	}
+
+	/**
+	 * 解析一个chain的过程
+	 *
+	 * @param chain 节点
+	 */
+	@Override
+	public abstract void parseOneChain(Element chain);
+}

部分文件因为文件数量过多而无法显示