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 c76fe8be4..0a4f426d7 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 @@ -146,13 +146,7 @@ public class LiteFlowChainELBuilder { } List errorList = new ArrayList<>(); try { - DefaultContext context = new DefaultContext<>(); - - // 往上下文里放入所有的node,使得el表达式可以直接引用到nodeId - FlowBus.getNodeMap().keySet().forEach(nodeId -> context.put(nodeId, FlowBus.getNode(nodeId))); - - // 解析route el成为一个executable - Executable routeExecutable = (Executable) EXPRESS_RUNNER.execute(routeEl, context, errorList, true, true); + Executable routeExecutable = compile(routeEl, errorList, false); // 判断routeEL是不是符合规范 if (!(routeExecutable instanceof AndOrCondition || routeExecutable instanceof NotCondition || routeExecutable instanceof Node)){ @@ -197,22 +191,7 @@ public class LiteFlowChainELBuilder { List errorList = new ArrayList<>(); try { - DefaultContext context = new DefaultContext<>(); - - // 这里一定要先放chain,再放node,因为node优先于chain,所以当重名时,node会覆盖掉chain - // 往上下文里放入所有的chain,是的el表达式可以直接引用到chain - FlowBus.getChainMap().values().forEach(chain -> context.put(chain.getChainId(), chain)); - - // 往上下文里放入所有的node,使得el表达式可以直接引用到nodeId - FlowBus.getNodeMap().keySet().forEach(nodeId -> context.put(nodeId, FlowBus.getNode(nodeId))); - - // 放入当前主chain的ID - context.put(ChainConstant.CURR_CHAIN_ID, this.chain.getChainId()); - - // 解析el成为一个Condition - // 为什么这里只是一个Condition,而不是一个List呢 - // 这里无论多复杂的,外面必定有一个最外层的Condition,所以这里只有一个,内部可以嵌套很多层,这点和以前的不太一样 - Condition condition = (Condition) EXPRESS_RUNNER.execute(elStr, context, errorList, true, true); + Condition condition = compile(elStr, errorList, true); if (Objects.isNull(condition)){ throw new QLException(StrUtil.format("parse el fail,el:[{}]", elStr)); @@ -269,7 +248,6 @@ public class LiteFlowChainELBuilder { * @param elStr EL表达式 * @return true 校验成功 false 校验失败 */ - @Deprecated public static boolean validate(String elStr) { return validateWithEx(elStr).isSuccess(); } @@ -277,16 +255,16 @@ public class LiteFlowChainELBuilder { /** * 校验 * - * @param elStr - * @return + * @param elStr EL表达式 + * @return ValidationResp */ public static ValidationResp validateWithEx(String elStr) { try { - LiteFlowChainELBuilder.createChain().setEL(elStr); + LiteFlowChainELBuilder.createChain().compile(elStr, null, true); return ValidationResp.success(); } catch (Exception e) { - LOG.error("validate error", e); - return ValidationResp.fail(e); + String msg = buildDataNotFoundExceptionMsg(elStr); + return ValidationResp.fail(new ELParseException(msg)); } } @@ -460,4 +438,29 @@ public class LiteFlowChainELBuilder { } } + @SuppressWarnings("unchecked") + private T compile(String elStr, List errorList, boolean putChain2Context) throws Exception{ + DefaultContext context = new DefaultContext<>(); + + if (putChain2Context){ + // 这里一定要先放chain,再放node,因为node优先于chain,所以当重名时,node会覆盖掉chain + // 往上下文里放入所有的chain,是的el表达式可以直接引用到chain + FlowBus.getChainMap().values().forEach(chain -> context.put(chain.getChainId(), chain)); + } + + // 往上下文里放入所有的node,使得el表达式可以直接引用到nodeId + FlowBus.getNodeMap().keySet().forEach(nodeId -> context.put(nodeId, FlowBus.getNode(nodeId))); + + // 放入当前主chain的ID + if (this.chain != null){ + context.put(ChainConstant.CURR_CHAIN_ID, this.chain.getChainId()); + } + + // 解析el成为一个Condition + // 为什么这里只是一个Condition,而不是一个List呢 + // 这里无论多复杂的,外面必定有一个最外层的Condition,所以这里只有一个,内部可以嵌套很多层,这点和以前的不太一样 + + return (T) EXPRESS_RUNNER.execute(elStr, context, errorList, true, true); + } + } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/validateRule/ValidateRuleELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/validateRule/ValidateRuleELSpringbootTest.java index 3511de711..38b1c4b39 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/validateRule/ValidateRuleELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/validateRule/ValidateRuleELSpringbootTest.java @@ -2,8 +2,10 @@ package com.yomahub.liteflow.test.validateRule; import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.common.entity.ValidationResp; import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.test.BaseTest; +import com.yomahub.liteflow.test.url.LiteflowNodeELSpringbootTest; import com.yomahub.liteflow.test.validateRule.cmp.ACmp; import com.yomahub.liteflow.test.validateRule.cmp.BCmp; import com.yomahub.liteflow.test.validateRule.cmp.CCmp; @@ -11,13 +13,15 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +@TestPropertySource(value = "classpath:/validate/application.properties") @SpringBootTest(classes = ValidateRuleELSpringbootTest.class) @EnableAutoConfiguration public class ValidateRuleELSpringbootTest extends BaseTest { @Test - public void testChainELExpressValidate() { + public void testChainELExpressValidate1() { LiteFlowNodeBuilder.createNode() .setId("a") .setName("组件A") @@ -36,8 +40,12 @@ public class ValidateRuleELSpringbootTest extends BaseTest { .setType(NodeTypeEnum.COMMON) .setClazz(CCmp.class) .build(); - Assertions.assertFalse(LiteFlowChainELBuilder.validate("THEN(a, b, h)")); - Assertions.assertTrue(LiteFlowChainELBuilder.validate("THEN(a, b, c)")); + + ValidationResp resp1 = LiteFlowChainELBuilder.validateWithEx("THEN(a, b, h)"); + ValidationResp resp2 = LiteFlowChainELBuilder.validateWithEx("THEN(a, b, c)"); + + Assertions.assertFalse(resp1.isSuccess()); + Assertions.assertTrue(resp2.isSuccess()); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/validate/application.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/validate/application.properties new file mode 100644 index 000000000..0b38cf3a7 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/validate/application.properties @@ -0,0 +1 @@ +liteflow.parse-mode=PARSE_ONE_ON_FIRST_EXEC \ No newline at end of file