diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowChainBuilder.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowChainBuilder.java deleted file mode 100644 index db62571b1..000000000 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowChainBuilder.java +++ /dev/null @@ -1,131 +0,0 @@ -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.yomahub.liteflow.enums.ConditionTypeEnum; -import com.yomahub.liteflow.flow.FlowBus; -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 - */ -public class LiteFlowChainBuilder { - - private Chain chain; - - //这是主体的Condition,不包含前置和后置 - //声明这个变量,而不是用chain.getConditionList的目的,是为了辅助平滑加载 - //虽然FlowBus里面的map都是CopyOnWrite类型的,但是在buildCondition的时候,为了平滑加载,所以不能事先把chain.getConditionList给设为空List - //所以在这里做一个缓存,等conditionList全部build完毕后,再去一次性替换chain里面的conditionList - private final List conditionList; - - //前置处理Condition,用来区别主体的Condition - private final List preConditionList; - - //后置处理Condition,用来区别主体的Condition - private final List finallyConditionList; - - public static LiteFlowChainBuilder createChain() { - return new 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的时候需要判断下 - /** - * - * @param chainName - * @return - * @deprecated 请使用 {@link #setChainId(String)} - */ - @Deprecated - public LiteFlowChainBuilder setChainName(String chainName) { - if (FlowBus.containChain(chainName)) { - this.chain = FlowBus.getChain(chainName); - } else { - this.chain.setChainName(chainName); - } - return this; - } - - public LiteFlowChainBuilder setChainId(String chainId) { - if (FlowBus.containChain(chainId)) { - this.chain = FlowBus.getChain(chainId); - } else { - this.chain.setChainId(chainId); - } - return this; - } - - public LiteFlowChainBuilder setCondition(Condition condition) { - //这里把condition组装进conditionList, - buildConditions(condition); - return this; - } - - 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 errorList = new ArrayList<>(); - 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.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).getExecutableList().addAll(condition.getExecutableList()); - } else { - this.conditionList.add(condition); - } - } else if (condition.getConditionType().equals(ConditionTypeEnum.TYPE_WHEN)) { - if (this.conditionList.size() >= 1 && - CollectionUtil.getLast(this.conditionList) instanceof WhenCondition && - ((WhenCondition)CollectionUtil.getLast(this.conditionList)).getGroup().equals(((WhenCondition)condition).getGroup())) { - CollectionUtil.getLast(this.conditionList).getExecutableList().addAll(condition.getExecutableList()); - } else { - this.conditionList.add(condition); - } - } - } -} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java index 4bcbeceb2..4fa7de4ac 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java @@ -12,7 +12,6 @@ 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; @@ -36,23 +35,13 @@ public class LiteFlowChainELBuilder { private Chain chain; /** - * //这是主体的Condition,不包含前置和后置 + * //这是主体的Condition * //声明这个变量,而不是用chain.getConditionList的目的,是为了辅助平滑加载 * //虽然FlowBus里面的map都是CopyOnWrite类型的,但是在buildCondition的时候,为了平滑加载,所以不能事先把chain.getConditionList给设为空List * //所以在这里做一个缓存,等conditionList全部build完毕后,再去一次性替换chain里面的conditionList */ private final List conditionList; - /** - * 前置处理Condition,用来区别主体的Condition - */ - private final List preConditionList; - - /** - * 后置处理Condition,用来区别主体的Condition - */ - private final List finallyConditionList; - /** * EL解析引擎 */ @@ -91,8 +80,6 @@ public class LiteFlowChainELBuilder { public LiteFlowChainELBuilder() { chain = new Chain(); conditionList = new ArrayList<>(); - preConditionList = new ArrayList<>(); - finallyConditionList = new ArrayList<>(); } //在parser中chain的build是2段式的,因为涉及到依赖问题,以前是递归parser @@ -150,13 +137,13 @@ public class LiteFlowChainELBuilder { //为什么只寻找第一层,而不往下寻找了呢? //因为这是一个规范,如果在后面的层级中出现pre和finally,语义上也不好理解,所以pre和finally只能定义在第一层 //如果硬是要在后面定义,则执行的时候会忽略,相关代码已做了判断 - for (Executable executable : condition.getExecutableList()) { + /*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); @@ -189,8 +176,6 @@ public class LiteFlowChainELBuilder { public void build() { this.chain.setConditionList(this.conditionList); - this.chain.setPreConditionList(this.preConditionList); - this.chain.setFinallyConditionList(this.finallyConditionList); checkBuild(); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java index a12827224..032044764 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java @@ -33,12 +33,6 @@ public class Chain implements Executable { private List conditionList = new ArrayList<>(); - //前置处理Condition,用来区别主体的Condition - private List preConditionList = new ArrayList<>(); - - //后置处理Condition,用来区别主体的Condition - private List finallyConditionList = new ArrayList<>(); - public Chain(String chainName){ this.chainId = chainName; } @@ -93,11 +87,9 @@ public class Chain implements Executable { try { //设置主ChainName slot.setChainId(chainId); - //执行前置 - this.executePre(slotIndex); //执行主体Condition for (Condition condition : conditionList) { - condition.setCurrChainName(chainId); + condition.setCurrChainId(chainId); condition.execute(slotIndex); } }catch (ChainEndException e){ @@ -112,23 +104,6 @@ public class Chain implements Executable { slot.setException(e); } throw e; - }finally { - //执行后置 - this.executeFinally(slotIndex); - } - } - - // 执行pre节点 - private void executePre(Integer slotIndex) throws Exception { - for (Condition condition : this.preConditionList){ - condition.execute(slotIndex); - } - } - - //执行后置 - private void executeFinally(Integer slotIndex) throws Exception { - for (Condition condition : this.finallyConditionList){ - condition.execute(slotIndex); } } @@ -141,19 +116,4 @@ public class Chain implements Executable { public String getExecuteId() { return chainId; } - public List getPreConditionList() { - return preConditionList; - } - - public void setPreConditionList(List preConditionList) { - this.preConditionList = preConditionList; - } - - public List getFinallyConditionList() { - return finallyConditionList; - } - - public void setFinallyConditionList(List finallyConditionList) { - this.finallyConditionList = finallyConditionList; - } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ThenCondition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ThenCondition.java index 394bc937c..842b488ad 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ThenCondition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ThenCondition.java @@ -8,13 +8,30 @@ package com.yomahub.liteflow.flow.element.condition; import com.yomahub.liteflow.enums.ConditionTypeEnum; +import com.yomahub.liteflow.exception.ChainEndException; import com.yomahub.liteflow.flow.element.Executable; +import com.yomahub.liteflow.slot.DataBus; +import com.yomahub.liteflow.slot.Slot; + +import java.util.ArrayList; +import java.util.List; /** * 串行器 * @author Bryan.Zhang */ public class ThenCondition extends Condition { + + /** + * 前置处理Condition + */ + private final List preConditionList = new ArrayList<>(); + + /** + * 后置处理Condition + */ + private final List finallyConditionList = new ArrayList<>(); + @Override public ConditionTypeEnum getConditionType() { return ConditionTypeEnum.TYPE_THEN; @@ -22,13 +39,44 @@ public class ThenCondition extends Condition { @Override public void execute(Integer slotIndex) throws Exception { - for (Executable executableItem : this.getExecutableList()) { - //前置和后置组不执行,因为在build的时候会抽出来放在chain里面 - if (executableItem instanceof PreCondition || executableItem instanceof FinallyCondition){ - continue; + try{ + for (PreCondition preCondition : preConditionList){ + preCondition.execute(slotIndex); } - executableItem.setCurrChainId(this.getCurrChainId()); - executableItem.execute(slotIndex); + + for (Executable executableItem : this.getExecutableList()) { + executableItem.setCurrChainId(this.getCurrChainId()); + executableItem.execute(slotIndex); + } + }catch (ChainEndException e){ + //这里单独catch ChainEndException是因为ChainEndException是用户自己setIsEnd抛出的异常 + //是属于正常逻辑,所以会在FlowExecutor中判断。这里不作为异常处理 + throw e; + }catch (Exception e){ + Slot slot = DataBus.getSlot(slotIndex); + String chainId = this.getCurrChainId(); + //这里事先取到exception set到slot里,为了方便finally取到exception + if (slot.isSubChain(chainId)){ + slot.setSubException(chainId, e); + }else{ + slot.setException(e); + } + throw e; + }finally { + for (FinallyCondition finallyCondition : finallyConditionList){ + finallyCondition.execute(slotIndex); + } + } + } + + @Override + public void addExecutable(Executable executable) { + if (executable instanceof PreCondition){ + preConditionList.add((PreCondition) executable); + }else if (executable instanceof FinallyCondition){ + finallyConditionList.add((FinallyCondition) executable); + }else{ + super.addExecutable(executable); } } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/exception/Exception2Test.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/exception/Exception2Test.java index b444ef82b..2757d5662 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/exception/Exception2Test.java +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/exception/Exception2Test.java @@ -1,6 +1,6 @@ package com.yomahub.liteflow.test.exception; -import com.yomahub.liteflow.builder.LiteFlowChainBuilder; +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.core.FlowExecutorHolder; import com.yomahub.liteflow.exception.ChainNotFoundException; @@ -43,7 +43,7 @@ public class Exception2Test extends BaseTest { @Test(expected = FlowSystemException.class) public void testNoConditionInChainException() throws Throwable { - LiteFlowChainBuilder.createChain().setChainName("chain2").build(); + LiteFlowChainELBuilder.createChain().setChainId("chain2").build(); LiteflowResponse response = flowExecutor.execute2Resp("chain2", "test"); Assert.assertFalse(response.isSuccess()); Assert.assertEquals("no conditionList in this chain[chain2]", response.getMessage()); diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/preAndFinally/PreAndFinallyELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/preAndFinally/PreAndFinallyELSpringbootTest.java index 791b29071..4b1605e2d 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/preAndFinally/PreAndFinallyELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/preAndFinally/PreAndFinallyELSpringbootTest.java @@ -70,4 +70,19 @@ public class PreAndFinallyELSpringbootTest extends BaseTest { Assert.assertTrue(response.isSuccess()); Assert.assertEquals("p1==>p2==>p1==>p2==>a==>b==>c==>f1==>f2==>f1", response.getExecuteStepStrWithoutTime()); } + + //测试变量结构pre和finally是否在各自的chain里打出 + @Test + public void testPreAndFinally6() throws Exception{ + LiteflowResponse response = flowExecutor.execute2Resp("chain6", "arg"); + Assert.assertTrue(response.isSuccess()); + Assert.assertEquals("p1==>p2==>p1==>p2==>a==>b==>c==>f1==>f2==>f1", response.getExecuteStepStrWithoutTime()); + } + + //测试el整体结构的多重pre和finally + @Test + public void testPreAndFinally7() throws Exception{ + LiteflowResponse response = flowExecutor.execute2Resp("chain7", "arg"); + Assert.assertTrue(response.isSuccess()); + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/preAndFinally/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/preAndFinally/flow.el.xml index d391acd07..4d7fcfe53 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/preAndFinally/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/preAndFinally/flow.el.xml @@ -19,4 +19,13 @@ THEN(PRE(p1, p2), chain1, FINALLY(f1)); + + + c1 = THEN(PRE(p1, p2), THEN(a, b, c), FINALLY(f1, f2)); + THEN(PRE(p1, p2), c1, FINALLY(f1)); + + + + THEN(a, b, THEN(PRE(p1), FINALLY(f1), c), PRE(p2), FINALLY(f2)); + \ No newline at end of file