diff --git a/.gitignore b/.gitignore
index 76b3603cf..9a8ec89b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -81,6 +81,5 @@ atlassian-ide-plugin.xml
*/logs
.flattened-pom.xml
-
.claude
.vscode
\ No newline at end of file
diff --git a/liteflow-benchmark/liteflow-benchmark-common-example/pom.xml b/liteflow-benchmark/liteflow-benchmark-common-example/pom.xml
index 821e4a241..d7358da76 100644
--- a/liteflow-benchmark/liteflow-benchmark-common-example/pom.xml
+++ b/liteflow-benchmark/liteflow-benchmark-common-example/pom.xml
@@ -16,7 +16,7 @@
com.yomahub
liteflow-script-javax-pro
- ${revision}
+ ${liteflow-version}
test
diff --git a/liteflow-benchmark/liteflow-benchmark-common/pom.xml b/liteflow-benchmark/liteflow-benchmark-common/pom.xml
index df0661fd8..fb62c3524 100644
--- a/liteflow-benchmark/liteflow-benchmark-common/pom.xml
+++ b/liteflow-benchmark/liteflow-benchmark-common/pom.xml
@@ -16,7 +16,7 @@
com.yomahub
liteflow-script-javax
- ${revision}
+ ${liteflow-version}
test
diff --git a/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/CommonBenchmark.java b/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/CommonBenchmark.java
index 275683423..43c9b1d55 100644
--- a/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/CommonBenchmark.java
+++ b/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/CommonBenchmark.java
@@ -1,10 +1,13 @@
package com.yomahub.liteflow.benchmark;
import cn.hutool.core.io.resource.ResourceUtil;
+import com.yomahub.liteflow.benchmark.cmp.TestContext;
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.FlowBus;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
@@ -42,7 +45,12 @@ public class CommonBenchmark {
@Benchmark
public void test1(){
- flowExecutor.execute2Resp("chain1");
+ TestContext context = new TestContext();
+ context.setName("tom");
+ context.setAge(21);
+ DefaultContext defaultContext = new DefaultContext();
+
+ flowExecutor.execute2Resp("chain1", null, context,defaultContext);
}
public static void main(String[] args) throws RunnerException {
diff --git a/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/CommonTest.java b/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/CommonTest.java
new file mode 100644
index 000000000..f8869ab68
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/CommonTest.java
@@ -0,0 +1,41 @@
+package com.yomahub.liteflow.benchmark;
+
+import cn.hutool.core.io.resource.ResourceUtil;
+import com.yomahub.liteflow.benchmark.cmp.TestContext;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.util.JsonUtil;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.annotation.Resource;
+
+@ExtendWith(SpringExtension.class)
+@TestPropertySource(value = "classpath:application.properties")
+@SpringBootTest(classes = CommonTest.class)
+@EnableAutoConfiguration
+@ComponentScan({ "com.yomahub.liteflow.benchmark.cmp" })
+public class CommonTest {
+
+ @Resource
+ private FlowExecutor flowExecutor;
+
+ @Test
+ public void test1() throws Exception {
+ TestContext context = new TestContext();
+ context.setName("tom");
+ context.setAge(21);
+ DefaultContext defaultContext = new DefaultContext();
+
+ LiteflowResponse response = flowExecutor.execute2Resp("chain1", null, context,defaultContext);
+ if (!response.isSuccess()){
+ throw response.getCause();
+ }
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/cmp/ACmp.java b/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/cmp/ACmp.java
index 4611110de..0ff485aa2 100644
--- a/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/cmp/ACmp.java
+++ b/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/cmp/ACmp.java
@@ -22,7 +22,7 @@ public class ACmp extends NodeComponent {
public void process() {
int v1 = 2;
int v2 = 3;
- DefaultContext ctx = this.getFirstContextBean();
+ DefaultContext ctx = this.getContextBean(DefaultContext.class);
ctx.setData("s1", v1 * v2);
TestDomain domain = ContextAwareHolder.loadContextAware().getBean(TestDomain.class);
diff --git a/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/cmp/CmpConfig.java b/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/cmp/CmpConfig.java
new file mode 100644
index 000000000..b31896602
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/cmp/CmpConfig.java
@@ -0,0 +1,21 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowFact;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent
+public class CmpConfig {
+
+ @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+ public void processA(NodeComponent bindCmp, @LiteflowFact("name") String name) {
+// System.out.println(name);
+ }
+
+ @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+ public void processB(NodeComponent bindCmp, @LiteflowFact("age") int age) {
+// System.out.println(age);
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/cmp/TestContext.java b/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/cmp/TestContext.java
new file mode 100644
index 000000000..df6f9430a
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-common/src/test/java/com/yomahub/liteflow/benchmark/cmp/TestContext.java
@@ -0,0 +1,24 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+public class TestContext {
+
+ private String name;
+
+ private int age;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-common/src/test/resources/flow.xml b/liteflow-benchmark/liteflow-benchmark-common/src/test/resources/flow.xml
index 41259eb42..45589ebd2 100644
--- a/liteflow-benchmark/liteflow-benchmark-common/src/test/resources/flow.xml
+++ b/liteflow-benchmark/liteflow-benchmark-common/src/test/resources/flow.xml
@@ -2,6 +2,6 @@
- THEN(a);
+ THEN(a,b,c);
\ No newline at end of file
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/pom.xml b/liteflow-benchmark/liteflow-benchmark-compile/pom.xml
new file mode 100644
index 000000000..63151a499
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/pom.xml
@@ -0,0 +1,16 @@
+
+
+ 4.0.0
+
+ liteflow-benchmark
+ com.yomahub
+ ${revision}
+ ../pom.xml
+
+
+ liteflow-benchmark-compile
+
+
+
\ No newline at end of file
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/TestCompile.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/TestCompile.java
new file mode 100644
index 000000000..7d9118790
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/TestCompile.java
@@ -0,0 +1,79 @@
+package com.yomahub.liteflow.benchmark;
+
+import cn.hutool.core.date.StopWatch;
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.annotation.Resource;
+
+@ExtendWith(SpringExtension.class)
+@TestPropertySource(value = "classpath:application.properties")
+@SpringBootTest(classes = TestCompile.class)
+@EnableAutoConfiguration
+@ComponentScan({ "com.yomahub.liteflow.benchmark.cmp" })
+public class TestCompile {
+
+ @Resource
+ private FlowExecutor flowExecutor;
+
+ @Test
+ public void test1() throws Exception {
+ LiteflowResponse response = flowExecutor.execute2Resp("channelSenderChain", null, BatchMessageResultContext.class);
+ BatchMessageResultContext context = response.getFirstContextBean();
+ if (response.isSuccess()){
+ System.out.println("执行成功,最终选择的渠道是:" + context.getFinalResultChannel());
+ }else{
+ System.out.println("执行失败:" + response.getCause());
+ }
+ }
+
+ //每个el都一样,走QL的缓存
+ @Test
+ public void test2() throws Exception {
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ String el = "selectBestChannel = THEN(WHEN(channel1Query, channel2Query, channel3Query,channel4Query, channel5Query, channel6Query),channelSelector).id(\"branch1\");\n" +
+ " selectBizChannel = THEN(biz1,SWITCH(if_2).to(channel3,channel4,SWITCH(if_3).to(channel5, channel6).id(\"s3\")).id(\"s2\")).id(\"branch2\");\n" +
+ " THEN(packageData,SWITCH(if_1).to(channel1,channel2,selectBestChannel,selectBizChannel),batchSender);";
+
+ for (int i = 1; i <= 20000; i++) {
+ LiteFlowChainELBuilder.createChain().setChainId("chain_build_"+i).setEL(el).build();
+ }
+
+ stopWatch.stop();
+
+ System.out.println(StrUtil.format("耗时:{}",stopWatch.getTotalTimeMillis()));
+
+ }
+
+ //每个el都不一样,不走QL的缓存
+ @Test
+ public void test3() throws Exception {
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ String el = "selectBestChannel = THEN(WHEN(channel1Query, channel2Query, channel3Query,channel4Query, channel5Query, channel6Query),channelSelector).id(\"branch1\");\n" +
+ " selectBizChannel = THEN(biz1,SWITCH(if_2).to(channel3,channel4,SWITCH(if_3).to(channel5, channel6).id(\"s3\")).id(\"s2\")).id(\"branch2\");\n" +
+ " THEN(packageData.tag(\"{}\"),SWITCH(if_1).to(channel1,channel2,selectBestChannel,selectBizChannel),batchSender);";
+
+ for (int i = 1; i <= 20000; i++) {
+ LiteFlowChainELBuilder.createChain().setChainId("chain_build_"+i).setEL(StrUtil.format(el,i)).build();
+ }
+
+ stopWatch.stop();
+
+ System.out.println(StrUtil.format("耗时:{}",stopWatch.getTotalTimeMillis()));
+
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/BatchSenderCmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/BatchSenderCmp.java
new file mode 100644
index 000000000..98aabc9ef
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/BatchSenderCmp.java
@@ -0,0 +1,21 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.core.NodeComponent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Random;
+
+@LiteflowComponent(id = "batchSender", name = "批量发送器")
+public class BatchSenderCmp extends NodeComponent {
+
+ private static final Logger log = LoggerFactory.getLogger(BatchSenderCmp.class);
+
+ @Override
+ public void process() throws Exception {
+ BatchMessageResultContext context = this.getFirstContextBean();
+ log.info("最终获取到的渠道为:[{}]", context.getFinalResultChannel());
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Biz1Cmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Biz1Cmp.java
new file mode 100644
index 000000000..74853a246
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Biz1Cmp.java
@@ -0,0 +1,13 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeComponent;
+
+import java.util.Random;
+
+@LiteflowComponent(id = "biz1", name = "获取业务动态值")
+public class Biz1Cmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel1Cmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel1Cmp.java
new file mode 100644
index 000000000..34c8b04ed
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel1Cmp.java
@@ -0,0 +1,14 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeComponent;
+
+@LiteflowComponent(id = "channel1", name = "返回渠道1")
+public class Channel1Cmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+ BatchMessageResultContext context = this.getFirstContextBean();
+ context.setFinalResultChannel("channel1");
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel1QueryCmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel1QueryCmp.java
new file mode 100644
index 000000000..0eaf3ac1f
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel1QueryCmp.java
@@ -0,0 +1,18 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.benchmark.vo.QueryVO;
+import com.yomahub.liteflow.core.NodeComponent;
+
+import java.util.Random;
+
+@LiteflowComponent(id = "channel1Query", name = "获取渠道1剩余量")
+public class Channel1QueryCmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+ //mock下渠道1有2w条剩余量
+ BatchMessageResultContext context = this.getFirstContextBean();
+ context.addQueryVO(new QueryVO("channel1", 20000));
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel2Cmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel2Cmp.java
new file mode 100644
index 000000000..8a326a0ec
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel2Cmp.java
@@ -0,0 +1,14 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeComponent;
+
+@LiteflowComponent(id = "channel2", name = "返回渠道2")
+public class Channel2Cmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+ BatchMessageResultContext context = this.getFirstContextBean();
+ context.setFinalResultChannel("channel2");
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel2QueryCmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel2QueryCmp.java
new file mode 100644
index 000000000..308d1339a
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel2QueryCmp.java
@@ -0,0 +1,19 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.benchmark.vo.QueryVO;
+import com.yomahub.liteflow.core.NodeComponent;
+
+import java.util.Random;
+
+@LiteflowComponent(id = "channel2Query", name = "获取渠道2剩余量")
+public class Channel2QueryCmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+
+ //mock下渠道2有1w条剩余量
+ BatchMessageResultContext context = this.getFirstContextBean();
+ context.addQueryVO(new QueryVO("channel2", 10000));
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel3Cmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel3Cmp.java
new file mode 100644
index 000000000..c32d667e9
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel3Cmp.java
@@ -0,0 +1,14 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeComponent;
+
+@LiteflowComponent(id = "channel3", name = "返回渠道3")
+public class Channel3Cmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+ BatchMessageResultContext context = this.getFirstContextBean();
+ context.setFinalResultChannel("channel3");
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel3QueryCmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel3QueryCmp.java
new file mode 100644
index 000000000..eb1765bf6
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel3QueryCmp.java
@@ -0,0 +1,19 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.benchmark.vo.QueryVO;
+import com.yomahub.liteflow.core.NodeComponent;
+
+import java.util.Random;
+
+@LiteflowComponent(id = "channel3Query", name = "获取渠道3剩余量")
+public class Channel3QueryCmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+
+ //mock下渠道3有10w条剩余量
+ BatchMessageResultContext context = this.getFirstContextBean();
+ context.addQueryVO(new QueryVO("channel3", 100000));
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel4Cmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel4Cmp.java
new file mode 100644
index 000000000..53232a4b0
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel4Cmp.java
@@ -0,0 +1,14 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeComponent;
+
+@LiteflowComponent(id = "channel4", name = "返回渠道4")
+public class Channel4Cmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+ BatchMessageResultContext context = this.getFirstContextBean();
+ context.setFinalResultChannel("channel4");
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel4QueryCmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel4QueryCmp.java
new file mode 100644
index 000000000..d886e3bd2
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel4QueryCmp.java
@@ -0,0 +1,18 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.benchmark.vo.QueryVO;
+import com.yomahub.liteflow.core.NodeComponent;
+
+import java.util.Random;
+
+@LiteflowComponent(id = "channel4Query", name = "获取渠道4剩余量")
+public class Channel4QueryCmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+ //mock下渠道4有7w条剩余量
+ BatchMessageResultContext context = this.getFirstContextBean();
+ context.addQueryVO(new QueryVO("channel4", 70000));
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel5Cmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel5Cmp.java
new file mode 100644
index 000000000..42553cee3
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel5Cmp.java
@@ -0,0 +1,14 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeComponent;
+
+@LiteflowComponent(id = "channel5", name = "返回渠道5")
+public class Channel5Cmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+ BatchMessageResultContext context = this.getFirstContextBean();
+ context.setFinalResultChannel("channel5");
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel5QueryCmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel5QueryCmp.java
new file mode 100644
index 000000000..e2c39c202
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel5QueryCmp.java
@@ -0,0 +1,18 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.benchmark.vo.QueryVO;
+import com.yomahub.liteflow.core.NodeComponent;
+
+import java.util.Random;
+
+@LiteflowComponent(id = "channel5Query", name = "获取渠道5剩余量")
+public class Channel5QueryCmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+ //mock下渠道5有5000条剩余量
+ BatchMessageResultContext context = this.getFirstContextBean();
+ context.addQueryVO(new QueryVO("channel5", 5000));
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel6Cmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel6Cmp.java
new file mode 100644
index 000000000..6b870690f
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel6Cmp.java
@@ -0,0 +1,14 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.core.NodeComponent;
+
+@LiteflowComponent(id = "channel6", name = "返回渠道6")
+public class Channel6Cmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+ BatchMessageResultContext context = this.getFirstContextBean();
+ context.setFinalResultChannel("channel6");
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel6QueryCmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel6QueryCmp.java
new file mode 100644
index 000000000..52c57fdf3
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/Channel6QueryCmp.java
@@ -0,0 +1,17 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.benchmark.vo.QueryVO;
+import com.yomahub.liteflow.core.NodeComponent;
+
+@LiteflowComponent(id = "channel6Query", name = "获取渠道6剩余量")
+public class Channel6QueryCmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+
+ //mock下渠道6有3w条剩余量
+ BatchMessageResultContext context = this.getFirstContextBean();
+ context.addQueryVO(new QueryVO("channel6", 30000));
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/ChannelSelectorCmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/ChannelSelectorCmp.java
new file mode 100644
index 000000000..9e8bee369
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/ChannelSelectorCmp.java
@@ -0,0 +1,24 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.benchmark.context.BatchMessageResultContext;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.benchmark.vo.QueryVO;
+import com.yomahub.liteflow.core.NodeComponent;
+
+import java.util.List;
+
+@LiteflowComponent(id = "channelSelector", name = "渠道余量最大选择器")
+public class ChannelSelectorCmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+ BatchMessageResultContext context = this.getFirstContextBean();
+
+ List queryList = context.getQueryResultList();
+
+ //选择渠道余量最大的
+ QueryVO vo = queryList.stream().min((o1, o2) -> o2.getAvailCount() - o1.getAvailCount()).orElse(null);
+
+ assert vo != null;
+ context.setFinalResultChannel(vo.getChannel());
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/IF1SwitchCmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/IF1SwitchCmp.java
new file mode 100644
index 000000000..8b505aad5
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/IF1SwitchCmp.java
@@ -0,0 +1,15 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeSwitchComponent;
+
+import java.util.Random;
+
+@LiteflowComponent(id = "if_1", name = "业务判断1")
+public class IF1SwitchCmp extends NodeSwitchComponent {
+ @Override
+ public String processSwitch() throws Exception {
+ //这里写死跳到并行获取剩余量那条分支,你可以改成其他分支测试
+ return "branch1";
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/IF2SwitchCmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/IF2SwitchCmp.java
new file mode 100644
index 000000000..d026238a8
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/IF2SwitchCmp.java
@@ -0,0 +1,15 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeSwitchComponent;
+
+import java.util.Random;
+
+@LiteflowComponent(id = "if_2", name = "业务判断2")
+public class IF2SwitchCmp extends NodeSwitchComponent {
+ @Override
+ public String processSwitch() throws Exception {
+ //这里写死,你可以改成其他分支
+ return "s3";
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/IF3SwitchCmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/IF3SwitchCmp.java
new file mode 100644
index 000000000..b2a27da52
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/IF3SwitchCmp.java
@@ -0,0 +1,16 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeSwitchComponent;
+
+import java.util.Random;
+
+@LiteflowComponent(id = "if_3", name = "业务判断3")
+public class IF3SwitchCmp extends NodeSwitchComponent {
+ @Override
+ public String processSwitch() throws Exception {
+
+ //这里写死,你可以改成其他
+ return "channel5";
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/PackageDataCmp.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/PackageDataCmp.java
new file mode 100644
index 000000000..e1648a420
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/cmp/PackageDataCmp.java
@@ -0,0 +1,13 @@
+package com.yomahub.liteflow.benchmark.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeComponent;
+
+import java.util.Random;
+
+@LiteflowComponent(id = "packageData", name = "组装数据")
+public class PackageDataCmp extends NodeComponent {
+ @Override
+ public void process() throws Exception {
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/context/BatchMessageResultContext.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/context/BatchMessageResultContext.java
new file mode 100644
index 000000000..b53142a6b
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/context/BatchMessageResultContext.java
@@ -0,0 +1,37 @@
+package com.yomahub.liteflow.benchmark.context;
+
+
+import com.yomahub.liteflow.benchmark.vo.QueryVO;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BatchMessageResultContext {
+
+ private List queryResultList;
+
+ private String finalResultChannel;
+
+ public List getQueryResultList() {
+ return queryResultList;
+ }
+
+ public void setQueryResultList(List queryResultList) {
+ this.queryResultList = queryResultList;
+ }
+
+ public String getFinalResultChannel() {
+ return finalResultChannel;
+ }
+
+ public void setFinalResultChannel(String finalResultChannel) {
+ this.finalResultChannel = finalResultChannel;
+ }
+
+ public void addQueryVO(QueryVO queryVO){
+ if (queryResultList == null){
+ queryResultList = new ArrayList<>();
+ }
+ queryResultList.add(queryVO);
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/vo/QueryVO.java b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/vo/QueryVO.java
new file mode 100644
index 000000000..53096cba9
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/java/com/yomahub/liteflow/benchmark/vo/QueryVO.java
@@ -0,0 +1,31 @@
+package com.yomahub.liteflow.benchmark.vo;
+
+public class QueryVO {
+
+ //渠道名称
+ private String channel;
+
+ //剩余短信包数量
+ private int availCount;
+
+ public QueryVO(String channel, int availCount) {
+ this.channel = channel;
+ this.availCount = availCount;
+ }
+
+ public String getChannel() {
+ return channel;
+ }
+
+ public void setChannel(String channel) {
+ this.channel = channel;
+ }
+
+ public int getAvailCount() {
+ return availCount;
+ }
+
+ public void setAvailCount(int availCount) {
+ this.availCount = availCount;
+ }
+}
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/resources/application.properties b/liteflow-benchmark/liteflow-benchmark-compile/src/test/resources/application.properties
new file mode 100644
index 000000000..c1d4f7007
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/resources/application.properties
@@ -0,0 +1,2 @@
+liteflow.rule-source=flow.xml
+liteflow.fast-load=true
\ No newline at end of file
diff --git a/liteflow-benchmark/liteflow-benchmark-compile/src/test/resources/flow.xml b/liteflow-benchmark/liteflow-benchmark-compile/src/test/resources/flow.xml
new file mode 100644
index 000000000..c8564c4b7
--- /dev/null
+++ b/liteflow-benchmark/liteflow-benchmark-compile/src/test/resources/flow.xml
@@ -0,0 +1,8 @@
+
+
+
+ selectBestChannel = THEN(WHEN(channel1Query, channel2Query, channel3Query,channel4Query, channel5Query, channel6Query),channelSelector).id("branch1");
+ selectBizChannel = THEN(biz1,SWITCH(if_2).to(channel3,channel4,SWITCH(if_3).to(channel5, channel6).id("s3")).id("s2")).id("branch2");
+ THEN(packageData,SWITCH(if_1).to(channel1,channel2,selectBestChannel,selectBizChannel),batchSender);
+
+
\ No newline at end of file
diff --git a/liteflow-benchmark/liteflow-benchmark-script-groovy/pom.xml b/liteflow-benchmark/liteflow-benchmark-script-groovy/pom.xml
index b2e0ea09a..441950941 100644
--- a/liteflow-benchmark/liteflow-benchmark-script-groovy/pom.xml
+++ b/liteflow-benchmark/liteflow-benchmark-script-groovy/pom.xml
@@ -16,7 +16,7 @@
com.yomahub
liteflow-script-groovy
- ${revision}
+ ${liteflow-version}
test
diff --git a/liteflow-benchmark/liteflow-benchmark-script-java/pom.xml b/liteflow-benchmark/liteflow-benchmark-script-java/pom.xml
index 139f0c987..8b4d9c8d6 100644
--- a/liteflow-benchmark/liteflow-benchmark-script-java/pom.xml
+++ b/liteflow-benchmark/liteflow-benchmark-script-java/pom.xml
@@ -16,7 +16,7 @@
com.yomahub
liteflow-script-java
- ${revision}
+ ${liteflow-version}
test
diff --git a/liteflow-benchmark/liteflow-benchmark-script-javax-pro/pom.xml b/liteflow-benchmark/liteflow-benchmark-script-javax-pro/pom.xml
index a2ef8108b..63f7e85ab 100644
--- a/liteflow-benchmark/liteflow-benchmark-script-javax-pro/pom.xml
+++ b/liteflow-benchmark/liteflow-benchmark-script-javax-pro/pom.xml
@@ -16,7 +16,7 @@
com.yomahub
liteflow-script-javax-pro
- ${revision}
+ ${liteflow-version}
test
diff --git a/liteflow-benchmark/liteflow-benchmark-script-javax/pom.xml b/liteflow-benchmark/liteflow-benchmark-script-javax/pom.xml
index 30405bb4c..5e3cc15f5 100644
--- a/liteflow-benchmark/liteflow-benchmark-script-javax/pom.xml
+++ b/liteflow-benchmark/liteflow-benchmark-script-javax/pom.xml
@@ -16,7 +16,7 @@
com.yomahub
liteflow-script-javax
- ${revision}
+ ${liteflow-version}
test
diff --git a/liteflow-benchmark/pom.xml b/liteflow-benchmark/pom.xml
index 4a57df63d..6cfbb2133 100644
--- a/liteflow-benchmark/pom.xml
+++ b/liteflow-benchmark/pom.xml
@@ -16,13 +16,14 @@
1.37
+ ${revision}
com.yomahub
liteflow-spring-boot-starter
- ${revision}
+ ${liteflow-version}
org.springframework.boot
@@ -48,5 +49,6 @@
liteflow-benchmark-script-groovy
liteflow-benchmark-common
liteflow-benchmark-common-example
+ liteflow-benchmark-compile
\ No newline at end of file
diff --git a/liteflow-core/pom.xml b/liteflow-core/pom.xml
index d650fa682..63fc7d6ba 100644
--- a/liteflow-core/pom.xml
+++ b/liteflow-core/pom.xml
@@ -54,7 +54,7 @@
com.alibaba
- QLExpress
+ qlexpress4
commons-beanutils
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 426315c8b..f495a4840 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
@@ -1,18 +1,20 @@
package com.yomahub.liteflow.builder.el;
import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.ql.util.express.DefaultContext;
-import com.ql.util.express.ExpressRunner;
-import com.ql.util.express.InstructionSet;
-import com.ql.util.express.exception.QLException;
-import com.yomahub.liteflow.builder.el.operator.*;
+import com.alibaba.qlexpress4.Express4Runner;
+import com.alibaba.qlexpress4.QLOptions;
+import com.alibaba.qlexpress4.QLResult;
+import com.alibaba.qlexpress4.exception.QLException;
+
+import java.util.HashMap;
+import java.util.Map;
+
import com.yomahub.liteflow.common.ChainConstant;
import com.yomahub.liteflow.common.entity.ValidationResp;
import com.yomahub.liteflow.enums.ParseModeEnum;
@@ -34,9 +36,9 @@ import com.yomahub.liteflow.util.ElRegexUtil;
import com.yomahub.liteflow.util.QlExpressUtils;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
@@ -70,7 +72,7 @@ public class LiteFlowChainELBuilder {
/**
* EL解析引擎
*/
- private final static ExpressRunner EXPRESS_RUNNER = QlExpressUtils.getInstance();
+ private final static Express4Runner EXPRESS_RUNNER = QlExpressUtils.getELExpressRunner();
public static LiteFlowChainELBuilder createChain() {
return new LiteFlowChainELBuilder();
@@ -131,15 +133,17 @@ public class LiteFlowChainELBuilder {
String msg = buildDataNotFoundExceptionMsg(routeEl);
throw new ELParseException(msg);
}else if (ObjectUtil.isNotNull(e.getCause())){
- throw new ELParseException(e.getCause().getMessage());
+ String causeMsg = e.getCause().getMessage();
+ throw new ELParseException(StrUtil.isNotBlank(causeMsg) ? causeMsg : e.getMessage());
}else{
- throw new ELParseException(e.getMessage());
+ throw new ELParseException(StrUtil.isNotBlank(e.getMessage()) ? e.getMessage() : "Unknown EL parse error");
}
}catch (RouteELInvalidException e){
throw e;
}catch (Exception e) {
String errMsg = StrUtil.format("parse el fail in this chain[{}];\r\n", chain.getChainId());
- throw new ELParseException(errMsg + e.getMessage());
+ String exMsg = e.getMessage();
+ throw new ELParseException(errMsg + (StrUtil.isNotBlank(exMsg) ? exMsg : e.getClass().getSimpleName()));
}
}
@@ -166,7 +170,7 @@ public class LiteFlowChainELBuilder {
Condition condition = compile(elStr, errorList, true);
if (Objects.isNull(condition)){
- throw new QLException(StrUtil.format("parse el fail,el:[{}]", elStr));
+ throw new ELParseException(StrUtil.format("parse el fail,el:[{}]", elStr));
}
if (liteflowConfig.getEnableNodeInstanceId()) {
@@ -178,18 +182,17 @@ public class LiteFlowChainELBuilder {
return this;
} catch (QLException e) {
// EL 底层会包装异常,这里是曲线处理
- if (ObjectUtil.isNotNull(e.getCause()) && Objects.equals(e.getCause().getMessage(), DataNotFoundException.MSG)) {
+ if (ObjectUtil.isNotNull(e.getCause())) {
// 构建错误信息
String msg = buildDataNotFoundExceptionMsg(elStr);
throw new ELParseException(msg);
- }else if (ObjectUtil.isNotNull(e.getCause())){
- throw new ELParseException(e.getCause().getMessage());
}else{
- throw new ELParseException(e.getMessage());
+ throw new ELParseException(StrUtil.isNotBlank(e.getMessage()) ? e.getMessage() : "Unknown EL parse error");
}
} catch (Exception e) {
String errMsg = StrUtil.format("parse el fail in this chain[{}];\r\n", chain.getChainId());
- throw new ELParseException(errMsg + e.getMessage());
+ String exMsg = e.getMessage();
+ throw new ELParseException(errMsg + (StrUtil.isNotBlank(exMsg) ? exMsg : e.getClass().getSimpleName()));
}
}
@@ -283,19 +286,15 @@ public class LiteFlowChainELBuilder {
String msg = String.format("[node/chain is not exist or node/chain not register]\n EL: %s",
StrUtil.trim(elStr));
try {
- InstructionSet parseResult = EXPRESS_RUNNER.getInstructionSetFromLocalCache(elStr);
- if (parseResult == null) {
- return msg;
- }
-
- String[] outAttrNames = parseResult.getOutAttrNames();
- if (ArrayUtil.isEmpty(outAttrNames)) {
+ // 使用 QLExpress4 的 getOutVarNames 方法获取脚本中使用的所有外部变量
+ Set outVarNames = EXPRESS_RUNNER.getOutVarNames(elStr);
+ if (CollUtil.isEmpty(outVarNames)) {
return msg;
}
List chainIds = CollUtil.map(FlowBus.getChainMap().values(), Chain::getChainId, true);
List nodeIds = CollUtil.map(FlowBus.getNodeMap().values(), Node::getId, true);
- for (String attrName : outAttrNames) {
+ for (String attrName : outVarNames) {
if (!chainIds.contains(attrName) && !nodeIds.contains(attrName)) {
msg = String.format(
"[%s] is not exist or [%s] is not registered, you need to define a node or chain with id [%s] and register it \n EL: ",
@@ -319,7 +318,7 @@ public class LiteFlowChainELBuilder {
// 还有一种特殊情况,就是 EL 表达式中的节点使用 node("a")
int nodeIndex = sourceEl.indexOf(String.format("node(\"%s\")", attrName));
if (nodeIndex != -1) {
- // 需要加上 "EL: " 的长度 4,再加上 “node("” 长度 6,再加上 "^" 的长度 1,indexOf 从 0
+ // 需要加上 "EL: " 的长度 4,再加上 "node("" 长度 6,再加上 "^" 的长度 1,indexOf 从 0
// 开始,所以还需要加 1
return msg + sourceEl + "\n" + StrUtil.fill("^", CharUtil.SPACE, commaLeftIndex + 12, true);
}
@@ -342,9 +341,8 @@ public class LiteFlowChainELBuilder {
return;
}
- List errorList = new ArrayList<>();
try {
- DefaultContext context = new DefaultContext<>();
+ Map context = new HashMap<>();
// 这里一定要先放chain,再放node,因为node优先于chain,所以当重名时,node会覆盖掉chain
// 往上下文里放入所有的chain,是的el表达式可以直接引用到chain
@@ -360,9 +358,8 @@ public class LiteFlowChainELBuilder {
// 只有当PARSE_ONE_ON_FIRST_EXEC时才会执行这个方法
// 那么会有一种级联的情况:这个EL中含有其他的chain,如果这时候不先解析其他chain,就到导致诸如循环场景无法设置index或者obj的情况
// 所以这里要判断表达式里有没有其他的chain,如果有,进行先行解析
-
- String[] itemArray = EXPRESS_RUNNER.getOutVarNames(chain.getEl());
- Arrays.stream(itemArray).forEach(item -> {
+ Set itemSet = EXPRESS_RUNNER.getOutVarNames(chain.getEl());
+ itemSet.stream().forEach(item -> {
if (FlowBus.containChain(item) && !chain.getChainId().equals(item)) {
Chain itemChain = FlowBus.getChain(item);
if (!itemChain.isCompiled()){
@@ -374,10 +371,11 @@ public class LiteFlowChainELBuilder {
// 解析el成为一个Condition
// 为什么这里只是一个Condition,而不是一个List呢
// 这里无论多复杂的,外面必定有一个最外层的Condition,所以这里只有一个,内部可以嵌套很多层,这点和以前的不太一样
- Condition condition = (Condition) EXPRESS_RUNNER.execute(chain.getEl(), context, errorList, true, true);
+ QLResult expressResult = EXPRESS_RUNNER.execute(chain.getEl(), context, QLOptions.builder().cache(true).build());
+ Condition condition = (Condition) expressResult.getResult();
if (Objects.isNull(condition)){
- throw new QLException(StrUtil.format("parse el fail,el:[{}]", chain.getEl()));
+ throw new ELParseException(StrUtil.format("parse el fail,el:[{}]", chain.getEl()));
}
// 设置实例id
@@ -400,19 +398,21 @@ public class LiteFlowChainELBuilder {
String msg = buildDataNotFoundExceptionMsg(chain.getEl());
throw new ELParseException(msg);
}else if (ObjectUtil.isNotNull(e.getCause())){
- throw new ELParseException(e.getCause().getMessage());
+ String causeMsg = e.getCause().getMessage();
+ throw new ELParseException(StrUtil.isNotBlank(causeMsg) ? causeMsg : e.getMessage());
}else{
- throw new ELParseException(e.getMessage());
+ throw new ELParseException(StrUtil.isNotBlank(e.getMessage()) ? e.getMessage() : "Unknown EL parse error");
}
} catch (Exception e) {
String errMsg = StrUtil.format("parse el fail in this chain[{}];\r\n", chain.getChainId());
- throw new ELParseException(errMsg + e.getMessage());
+ String exMsg = e.getMessage();
+ throw new ELParseException(errMsg + (StrUtil.isNotBlank(exMsg) ? exMsg : e.getClass().getSimpleName()));
}
}
@SuppressWarnings("unchecked")
private T compile(String elStr, List errorList, boolean putChain2Context) throws Exception{
- DefaultContext context = new DefaultContext<>();
+ Map context = new HashMap<>();
if (putChain2Context){
// 这里一定要先放chain,再放node,因为node优先于chain,所以当重名时,node会覆盖掉chain
@@ -431,8 +431,8 @@ public class LiteFlowChainELBuilder {
// 解析el成为一个Condition
// 为什么这里只是一个Condition,而不是一个List呢
// 这里无论多复杂的,外面必定有一个最外层的Condition,所以这里只有一个,内部可以嵌套很多层,这点和以前的不太一样
-
- return (T) EXPRESS_RUNNER.execute(elStr, context, errorList, true, true);
+ QLResult expressResult = EXPRESS_RUNNER.execute(elStr, context, QLOptions.builder().cache(true).build());
+ return (T) expressResult.getResult();
}
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/DoOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/DoOperator.java
index c6b3a5f4a..98e840c5d 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/DoOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/DoOperator.java
@@ -1,6 +1,6 @@
package com.yomahub.liteflow.builder.el.operator;
-import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
import com.yomahub.liteflow.flow.element.Executable;
@@ -41,7 +41,7 @@ public class DoOperator extends BaseOperator {
}
else {
String errorMsg = "The caller must be LoopCondition or CatchCondition item";
- throw new QLException(errorMsg);
+ throw new ELParseException(errorMsg);
}
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/FinallyOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/FinallyOperator.java
index b759b6cac..fc5f3cc0a 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/FinallyOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/FinallyOperator.java
@@ -1,6 +1,6 @@
package com.yomahub.liteflow.builder.el.operator;
-import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
import com.yomahub.liteflow.flow.element.Executable;
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ForOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ForOperator.java
index a5abc57f0..393986a9b 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ForOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ForOperator.java
@@ -3,7 +3,7 @@ package com.yomahub.liteflow.builder.el.operator;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
-import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
import com.yomahub.liteflow.core.NodeComponent;
@@ -46,7 +46,7 @@ public class ForOperator extends BaseOperator {
node.setId(nodeForComponent.getNodeId());
}
else {
- throw new QLException("The parameter must be Node item");
+ throw new ELParseException("The parameter must be Node item");
}
ForCondition forCondition = new ForCondition();
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IgnoreErrorOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IgnoreErrorOperator.java
index b140dce46..dfb36fa4e 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IgnoreErrorOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IgnoreErrorOperator.java
@@ -1,6 +1,6 @@
package com.yomahub.liteflow.builder.el.operator;
-import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
import com.yomahub.liteflow.flow.element.condition.WhenCondition;
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java
index 0d29a7f07..f35ecb5a8 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java
@@ -1,7 +1,7 @@
package com.yomahub.liteflow.builder.el.operator;
import cn.hutool.core.collection.ListUtil;
-import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
import com.yomahub.liteflow.enums.NodeTypeEnum;
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitTimeOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitTimeOperator.java
index 6ca3fd3ec..37d586f3a 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitTimeOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitTimeOperator.java
@@ -2,7 +2,7 @@ package com.yomahub.liteflow.builder.el.operator;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrFormatter;
-import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
import com.yomahub.liteflow.flow.element.Condition;
@@ -42,7 +42,7 @@ public abstract class MaxWaitTimeOperator extends BaseOperator {
} else if (executable instanceof FinallyCondition) {
// FINALLY,报错
String errorMsg = StrFormatter.format("The caller [{}] cannot use the keyword \"{}'\"", executable.toString(), operatorName());
- throw new QLException(errorMsg);
+ throw new ELParseException(errorMsg);
} else if (containsFinally(executable)) {
// 处理 THEN 中的 FINALLY
ThenCondition thenCondition = OperatorHelper.convert(executable, ThenCondition.class);
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/PercentageOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/PercentageOperator.java
index 0bb172f3a..100d127bc 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/PercentageOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/PercentageOperator.java
@@ -1,6 +1,6 @@
package com.yomahub.liteflow.builder.el.operator;
-import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
import com.yomahub.liteflow.enums.ParallelStrategyEnum;
@@ -24,7 +24,7 @@ public class PercentageOperator extends BaseOperator {
Double percentage = OperatorHelper.convert2Double(objects[1]);
if (percentage > 1 || percentage < 0) {
- throw new QLException("The percentage must be between 0 and 1.");
+ throw new ELParseException("The percentage must be between 0 and 1.");
}
whenCondition.setParallelStrategy(ParallelStrategyEnum.PERCENTAGE);
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java
index c1d0ad3d9..693368663 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java
@@ -1,7 +1,7 @@
package com.yomahub.liteflow.builder.el.operator;
import cn.hutool.core.collection.ListUtil;
-import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
import com.yomahub.liteflow.enums.NodeTypeEnum;
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/TagOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/TagOperator.java
index 2d61e59b3..451328e89 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/TagOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/TagOperator.java
@@ -1,7 +1,7 @@
package com.yomahub.liteflow.builder.el.operator;
import cn.hutool.core.collection.ListUtil;
-import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
import com.yomahub.liteflow.flow.FlowBus;
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ThreadPoolOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ThreadPoolOperator.java
index 69f444fcb..963e1233f 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ThreadPoolOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ThreadPoolOperator.java
@@ -1,6 +1,6 @@
package com.yomahub.liteflow.builder.el.operator;
-import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
import com.yomahub.liteflow.flow.element.Condition;
@@ -37,7 +37,7 @@ public class ThreadPoolOperator extends BaseOperator {
return condition;
} else {
String errorMsg = "The caller must be WhenCondition or LoopCondition item";
- throw new QLException(errorMsg);
+ throw new ELParseException(errorMsg);
}
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/BaseOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/BaseOperator.java
index b0a02eea9..f61db65dc 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/BaseOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/BaseOperator.java
@@ -1,23 +1,23 @@
package com.yomahub.liteflow.builder.el.operator.base;
-import com.ql.util.express.Operator;
-import com.ql.util.express.exception.QLException;
+import com.alibaba.qlexpress4.api.QLFunctionalVarargs;
+import com.alibaba.qlexpress4.exception.QLException;
import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.flow.element.Executable;
/**
- * BaseOperator 为了强化 executeInner 方法,会捕获抛出的 QLException 错误,输出友好的错误提示
+ * BaseOperator 为了强化 call 方法,会捕获抛出的 QLException 错误,输出友好的错误提示
*
* @author gaibu
* @since 2.8.6
*/
-public abstract class BaseOperator extends Operator {
+public abstract class BaseOperator implements QLFunctionalVarargs {
@Override
- public T executeInner(Object[] objects) throws Exception {
+ public T call(Object... parameters) {
try {
- OperatorHelper.checkItemNotNull(objects);
- return build(objects);
+ OperatorHelper.checkItemNotNull(parameters);
+ return build(parameters);
}
catch (QLException e) {
throw e;
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java
index 31107a9d9..d1d9bf41f 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java
@@ -2,11 +2,11 @@ package com.yomahub.liteflow.builder.el.operator.base;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
-import com.ql.util.express.exception.QLException;
import com.yomahub.liteflow.enums.ConditionTypeEnum;
import com.yomahub.liteflow.enums.ExecuteableTypeEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.exception.DataNotFoundException;
+import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.flow.element.Condition;
import com.yomahub.liteflow.flow.element.Executable;
import com.yomahub.liteflow.flow.element.Node;
@@ -25,50 +25,50 @@ public class OperatorHelper {
/**
* 检查参数数量,大于 0
* @param objects objects
- * @throws QLException QLException
+ * @throws ELParseException ELParseException
*/
- public static void checkObjectSizeGtZero(Object[] objects) throws QLException {
+ public static void checkObjectSizeGtZero(Object[] objects) throws ELParseException {
if (objects.length == 0) {
- throw new QLException("parameter is empty");
+ throw new ELParseException("parameter is empty");
}
}
/**
* 检查参数数量,大于等于 2
* @param objects objects
- * @throws QLException QLException
+ * @throws ELParseException ELParseException
*/
- public static void checkObjectSizeGteTwo(Object[] objects) throws QLException {
+ public static void checkObjectSizeGteTwo(Object[] objects) throws ELParseException {
checkObjectSizeGtZero(objects);
if (objects.length < 2) {
- throw new QLException("parameter size error");
+ throw new ELParseException("parameter size error");
}
}
/**
* 检查参数数量,等于 1
* @param objects objects
- * @throws QLException QLException
+ * @throws ELParseException ELParseException
*/
- public static void checkObjectSizeEqOne(Object[] objects) throws QLException {
+ public static void checkObjectSizeEqOne(Object[] objects) throws ELParseException {
checkObjectSizeEq(objects, 1);
}
/**
* 检查参数数量,等于 2
* @param objects objects
- * @throws QLException QLException
+ * @throws ELParseException ELParseException
*/
- public static void checkObjectSizeEqTwo(Object[] objects) throws QLException {
+ public static void checkObjectSizeEqTwo(Object[] objects) throws ELParseException {
checkObjectSizeEq(objects, 2);
}
/**
* 检查参数数量,等于 3
* @param objects objects
- * @throws QLException QLException
+ * @throws ELParseException ELParseException
*/
- public static void checkObjectSizeEqThree(Object[] objects) throws QLException {
+ public static void checkObjectSizeEqThree(Object[] objects) throws ELParseException {
checkObjectSizeEq(objects, 3);
}
@@ -76,13 +76,13 @@ public class OperatorHelper {
* 检查参数数量,等于 size
* @param objects objects
* @param size 参数数量
- * @throws QLException QLException
+ * @throws ELParseException ELParseException
*/
- public static void checkObjectSizeEq(Object[] objects, int size) throws QLException {
+ public static void checkObjectSizeEq(Object[] objects, int size) throws ELParseException {
checkObjectSizeGtZero(objects);
if (objects.length != size) {
- throw new QLException("parameter size error");
+ throw new ELParseException("parameter size error");
}
}
@@ -91,13 +91,13 @@ public class OperatorHelper {
* @param objects objects
* @param size1 参数数量1
* @param size2 参数数量2
- * @throws QLException QLException
+ * @throws ELParseException ELParseException
*/
- public static void checkObjectSizeEq(Object[] objects, int size1, int size2) throws QLException {
+ public static void checkObjectSizeEq(Object[] objects, int size1, int size2) throws ELParseException {
checkObjectSizeGtZero(objects);
if (objects.length != size1 && objects.length != size2) {
- throw new QLException("parameter size error");
+ throw new ELParseException("parameter size error");
}
}
@@ -105,12 +105,12 @@ public class OperatorHelper {
* 转换 object 为指定的类型 如果是Node类型的则进行copy
* 为什么要进行copy呢?因为原先的Node都是存放在FlowBus的NodeMap中的。有些属性在EL中不是全局的,属于当前这个chain的。 所以要进行copy动作
*/
- public static T convert(Object object, Class clazz) throws QLException {
+ public static T convert(Object object, Class clazz) throws ELParseException {
String errorMsg = StrUtil.format("The parameter must be {} item", clazz.getSimpleName());
return convert(object, clazz, errorMsg);
}
- public static Double convert2Double(Object object) throws QLException {
+ public static Double convert2Double(Object object) throws ELParseException {
if (object instanceof Number) {
// 对 float 特别处理,避免精度问题
if (object instanceof Float) {
@@ -119,14 +119,14 @@ public class OperatorHelper {
}
return ((Number) object).doubleValue();
}
- throw new QLException(StrUtil.format("Unsupported type: {}, it must be numeric type.", object.getClass().getName()));
+ throw new ELParseException(StrUtil.format("Unsupported type: {}, it must be numeric type.", object.getClass().getName()));
}
/**
* 转换 object 为指定的类型,自定义错误信息 如果是Node类型的则进行copy
*/
@SuppressWarnings("unchecked")
- public static T convert(Object object, Class clazz, String errorMsg) throws QLException {
+ public static T convert(Object object, Class clazz, String errorMsg) throws ELParseException {
try {
if (clazz.isAssignableFrom(object.getClass())) {
if (object instanceof Node) {
@@ -139,16 +139,16 @@ public class OperatorHelper {
}
}
catch (Exception e) {
- throw new QLException("An error occurred while copying an object");
+ throw new ELParseException("An error occurred while copying an object");
}
- throw new QLException(errorMsg);
+ throw new ELParseException(errorMsg);
}
- public static void checkItemNotNull(Object[] objects) throws QLException {
+ public static void checkItemNotNull(Object[] objects) throws ELParseException {
for (Object object : objects) {
if (Objects.isNull(object)) {
- throw new QLException(DataNotFoundException.MSG);
+ throw new ELParseException(DataNotFoundException.MSG);
}
}
}
@@ -159,13 +159,13 @@ public class OperatorHelper {
*/
public static void checkObjMustBeCommonTypeItem(Object object) throws Exception{
if (!(object instanceof Executable)){
- throw new QLException("The parameter must be Executable item.");
+ throw new ELParseException("The parameter must be Executable item.");
}
Executable item = (Executable) object;
if (item.getExecuteType().equals(ExecuteableTypeEnum.NODE)){
Node node = (Node) item;
if (!ListUtil.toList(NodeTypeEnum.COMMON, NodeTypeEnum.SCRIPT, NodeTypeEnum.FALLBACK).contains(node.getType())){
- throw new QLException(StrUtil.format("The node[{}] must be a common type component", node.getId()));
+ throw new ELParseException(StrUtil.format("The node[{}] must be a common type component", node.getId()));
}
}
}
@@ -178,7 +178,7 @@ public class OperatorHelper {
*/
public static void checkObjMustBeBooleanTypeItem(Object object) throws Exception{
if (!(object instanceof Executable)){
- throw new QLException("The parameter must be Executable item.");
+ throw new ELParseException("The parameter must be Executable item.");
}
Executable item = (Executable) object;
if (item.getExecuteType().equals(ExecuteableTypeEnum.NODE)){
@@ -186,21 +186,21 @@ public class OperatorHelper {
if (!ListUtil.toList(NodeTypeEnum.BOOLEAN,
NodeTypeEnum.BOOLEAN_SCRIPT,
NodeTypeEnum.FALLBACK).contains(node.getType())){
- throw new QLException(StrUtil.format("The node[{}] must be boolean type Node.", node.getId()));
+ throw new ELParseException(StrUtil.format("The node[{}] must be boolean type Node.", node.getId()));
}
}else if(item.getExecuteType().equals(ExecuteableTypeEnum.CONDITION)){
Condition condition = (Condition) item;
if (!ListUtil.toList(ConditionTypeEnum.TYPE_AND_OR_OPT, ConditionTypeEnum.TYPE_NOT_OPT).contains(condition.getConditionType())){
- throw new QLException(StrUtil.format("The condition[{}] must be boolean type Condition.", condition.getId()));
+ throw new ELParseException(StrUtil.format("The condition[{}] must be boolean type Condition.", condition.getId()));
}
}else{
- throw new QLException("The parameter error.");
+ throw new ELParseException("The parameter error.");
}
}
public static void checkObjMustBeForTypeItem(Object object) throws Exception{
if (!(object instanceof Executable)){
- throw new QLException("The parameter must be Executable item.");
+ throw new ELParseException("The parameter must be Executable item.");
}
Executable item = (Executable) object;
if (item.getExecuteType().equals(ExecuteableTypeEnum.NODE)){
@@ -208,32 +208,32 @@ public class OperatorHelper {
if (!ListUtil.toList(NodeTypeEnum.FOR,
NodeTypeEnum.FOR_SCRIPT,
NodeTypeEnum.FALLBACK).contains(node.getType())){
- throw new QLException(StrUtil.format("The node[{}] must be For type Node.", node.getId()));
+ throw new ELParseException(StrUtil.format("The node[{}] must be For type Node.", node.getId()));
}
}else{
- throw new QLException("The parameter error.");
+ throw new ELParseException("The parameter error.");
}
}
public static void checkObjMustBeIteratorTypeItem(Object object) throws Exception{
if (!(object instanceof Executable)){
- throw new QLException("The parameter must be Executable item.");
+ throw new ELParseException("The parameter must be Executable item.");
}
Executable item = (Executable) object;
if (item.getExecuteType().equals(ExecuteableTypeEnum.NODE)){
Node node = (Node) item;
if (!ListUtil.toList(NodeTypeEnum.ITERATOR,
NodeTypeEnum.FALLBACK).contains(node.getType())){
- throw new QLException(StrUtil.format("The node[{}] must be Iterator type Node.", node.getId()));
+ throw new ELParseException(StrUtil.format("The node[{}] must be Iterator type Node.", node.getId()));
}
}else{
- throw new QLException("The parameter error.");
+ throw new ELParseException("The parameter error.");
}
}
public static void checkObjMustBeSwitchTypeItem(Object object) throws Exception{
if (!(object instanceof Executable)){
- throw new QLException("The parameter must be Executable item.");
+ throw new ELParseException("The parameter must be Executable item.");
}
Executable item = (Executable) object;
if (item.getExecuteType().equals(ExecuteableTypeEnum.NODE)){
@@ -241,10 +241,10 @@ public class OperatorHelper {
if (!ListUtil.toList(NodeTypeEnum.SWITCH,
NodeTypeEnum.SWITCH_SCRIPT,
NodeTypeEnum.FALLBACK).contains(node.getType())){
- throw new QLException(StrUtil.format("The node[{}] must be Switch type Node.", node.getId()));
+ throw new ELParseException(StrUtil.format("The node[{}] must be Switch type Node.", node.getId()));
}
}else{
- throw new QLException("The parameter error.");
+ throw new ELParseException("The parameter error.");
}
}
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/proxy/DeclComponentProxy.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/proxy/DeclComponentProxy.java
index 905d89847..8104ec8ea 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/proxy/DeclComponentProxy.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/proxy/DeclComponentProxy.java
@@ -6,9 +6,9 @@ import cn.hutool.core.lang.Tuple;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
-import com.ql.util.express.DefaultContext;
-import com.ql.util.express.ExpressRunner;
-import com.ql.util.express.InstructionSet;
+import com.alibaba.qlexpress4.Express4Runner;
+import com.alibaba.qlexpress4.QLResult;
+import com.alibaba.qlexpress4.QLOptions;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.annotation.LiteflowRetry;
import com.yomahub.liteflow.core.NodeComponent;
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/instanceId/BaseNodeInstanceIdManageSpi.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/instanceId/BaseNodeInstanceIdManageSpi.java
index b18ef6467..38415a34c 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/instanceId/BaseNodeInstanceIdManageSpi.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/instanceId/BaseNodeInstanceIdManageSpi.java
@@ -1,13 +1,13 @@
package com.yomahub.liteflow.flow.instanceId;
import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.flow.element.Chain;
import com.yomahub.liteflow.flow.element.Condition;
import com.yomahub.liteflow.flow.element.Node;
import com.yomahub.liteflow.flow.entity.InstanceInfoDto;
import com.yomahub.liteflow.util.JsonUtil;
-import org.apache.commons.lang.StringUtils;
import java.util.*;
@@ -26,7 +26,7 @@ public abstract class BaseNodeInstanceIdManageSpi implements NodeInstanceIdManag
*/
@Override
public Node getNodeByIdAndInstanceId(String chainId, String instanceId) {
- if (StringUtils.isBlank(chainId) || StringUtils.isBlank(instanceId)) {
+ if (StrUtil.isBlank(chainId) || StrUtil.isBlank(instanceId)) {
return null;
}
Chain chain = FlowBus.getChain(chainId);
@@ -45,7 +45,7 @@ public abstract class BaseNodeInstanceIdManageSpi implements NodeInstanceIdManag
*/
@Override
public Node getNodeByIdAndIndex(String chainId, String nodeId, Integer index) {
- if (StringUtils.isBlank(chainId) || index == null) {
+ if (StrUtil.isBlank(chainId) || index == null) {
return null;
}
Chain chain = FlowBus.getChain(chainId);
@@ -64,7 +64,7 @@ public abstract class BaseNodeInstanceIdManageSpi implements NodeInstanceIdManag
*/
@Override
public List getNodeInstanceIds(String chainId, String nodeId) {
- if (StringUtils.isBlank(chainId) || StringUtils.isBlank(nodeId)) {
+ if (StrUtil.isBlank(chainId) || StrUtil.isBlank(nodeId)) {
return Collections.emptyList();
}
// 第一行为elMd5 第二行为实例id json格式信息
@@ -133,7 +133,7 @@ public abstract class BaseNodeInstanceIdManageSpi implements NodeInstanceIdManag
*/
@Override
public int getNodeLocationById(String chainId, String instanceId) {
- if (StringUtils.isBlank(chainId) || StringUtils.isBlank(instanceId)) {
+ if (StrUtil.isBlank(chainId) || StrUtil.isBlank(instanceId)) {
return -1;
}
// 第一行为elMd5 第二行为实例id json格式信息
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/instanceId/DefaultNodeInstanceIdManageSpiImpl.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/instanceId/DefaultNodeInstanceIdManageSpiImpl.java
index cc94e8185..da8ed5dca 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/instanceId/DefaultNodeInstanceIdManageSpiImpl.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/instanceId/DefaultNodeInstanceIdManageSpiImpl.java
@@ -3,9 +3,9 @@ package com.yomahub.liteflow.flow.instanceId;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.flow.entity.InstanceInfoDto;
import com.yomahub.liteflow.util.JsonUtil;
-import org.apache.commons.lang.StringUtils;
import java.io.File;
import java.util.*;
@@ -23,7 +23,7 @@ public class DefaultNodeInstanceIdManageSpiImpl extends BaseNodeInstanceIdManage
@Override
public List readInstanceIdFile(String chainId) {
- if (StringUtils.isBlank(chainId)) {
+ if (StrUtil.isBlank(chainId)) {
return Collections.emptyList();
}
@@ -36,7 +36,7 @@ public class DefaultNodeInstanceIdManageSpiImpl extends BaseNodeInstanceIdManage
@Override
public void writeInstanceIdFile(List instanceIdList, String elMd5, String chainId) {
- if (StringUtils.isBlank(chainId) || CollUtil.isEmpty(instanceIdList)) {
+ if (StrUtil.isBlank(chainId) || CollUtil.isEmpty(instanceIdList)) {
return;
}
File nodeDir = new File(basePath + chainId);
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/util/LiteflowContextRegexMatcher.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/LiteflowContextRegexMatcher.java
index a626caecd..1ba6e11b9 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/util/LiteflowContextRegexMatcher.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/LiteflowContextRegexMatcher.java
@@ -4,12 +4,14 @@ import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Tuple;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
-import com.ql.util.express.DefaultContext;
-import com.ql.util.express.ExpressRunner;
-import com.ql.util.express.InstructionSet;
+import com.alibaba.qlexpress4.Express4Runner;
+import com.alibaba.qlexpress4.QLResult;
+import com.alibaba.qlexpress4.InitOptions;
+import com.alibaba.qlexpress4.QLOptions;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
@@ -26,7 +28,7 @@ import java.util.stream.IntStream;
*/
public class LiteflowContextRegexMatcher {
- private static final ExpressRunner expressRunner = new ExpressRunner();
+ private static final Express4Runner expressRunner = QlExpressUtils.getContextSearchExpressRunner();
public static Object searchContext(List contextList, String regPattern){
// 把上下文数据转换成map形式的,key为别名,value为上下文
@@ -34,16 +36,14 @@ public class LiteflowContextRegexMatcher {
Collectors.toMap(tuple -> tuple.get(0), tuple -> tuple.get(1))
);
- List errorList = new ArrayList<>();
-
Object result = null;
// 根据表达式去上下文里搜索相匹配的数据
for(Map.Entry entry : contextMap.entrySet()){
try{
- InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache(entry.getKey() + "." + regPattern);
- DefaultContext context = new DefaultContext<>();
+ Map context = new HashMap<>();
context.put(entry.getKey(), entry.getValue());
- result = expressRunner.execute(instructionSet, context, errorList, false, false);
+ QLResult expressResult = expressRunner.execute(entry.getKey() + "." + regPattern, context, QLOptions.builder().cache(true).build());
+ result = expressResult.getResult();
if (result != null){
break;
}
@@ -53,10 +53,10 @@ public class LiteflowContextRegexMatcher {
if (result == null){
try{
// 如果没有搜到,那么尝试推断表达式是指定的上下文,按照指定上下文的方式去再获取
- InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache("contextMap." + regPattern);
- DefaultContext context = new DefaultContext<>();
+ Map context = new HashMap<>();
context.put("contextMap", contextMap);
- result = expressRunner.execute(instructionSet, context, errorList, false, false);
+ QLResult expressResult = expressRunner.execute("contextMap." + regPattern, context, QLOptions.builder().cache(true).build());
+ result = expressResult.getResult();
}catch (Exception ignore){}
}
@@ -69,8 +69,6 @@ public class LiteflowContextRegexMatcher {
Collectors.toMap(tuple -> tuple.get(0), tuple -> tuple.get(1))
);
- List errorList = new ArrayList<>();
-
boolean flag = false;
String argStr = IntStream.range(0, args.length).mapToObj(
@@ -83,11 +81,10 @@ public class LiteflowContextRegexMatcher {
for(Map.Entry entry : contextMap.entrySet()){
try{
- InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache(StrUtil.format("{}.{}({})", entry.getKey(), methodExpress, argStr));
- DefaultContext context = new DefaultContext<>();
+ Map context = new HashMap<>();
context.put(entry.getKey(), entry.getValue());
tupleList.forEach(tuple -> context.put(tuple.getA(), args[tuple.getB()]));
- expressRunner.execute(instructionSet, context, errorList, false, false);
+ expressRunner.execute(StrUtil.format("{}.{}({})", entry.getKey(), methodExpress, argStr), context, QLOptions.builder().cache(true).build());
flag = true;
break;
}catch (Exception ignore){}
@@ -97,11 +94,10 @@ public class LiteflowContextRegexMatcher {
if (BooleanUtil.isFalse(flag)){
try{
// 如果没有搜到,那么尝试推断表达式是指定的上下文,按照指定上下文的方式去再获取
- InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache(StrUtil.format("contextMap.{}({})", methodExpress, argStr));
- DefaultContext context = new DefaultContext<>();
+ Map context = new HashMap<>();
context.put("contextMap", contextMap);
tupleList.forEach(tuple -> context.put(tuple.getA(), args[tuple.getB()]));
- expressRunner.execute(instructionSet, context, errorList, false, false);
+ expressRunner.execute(StrUtil.format("contextMap.{}({})", methodExpress, argStr), context, QLOptions.builder().cache(true).build());
}catch (Exception ignore){}
}
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/util/QlExpressUtils.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/QlExpressUtils.java
index 0dac32a61..8828d99c2 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/util/QlExpressUtils.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/QlExpressUtils.java
@@ -1,6 +1,9 @@
package com.yomahub.liteflow.util;
-import com.ql.util.express.ExpressRunner;
+import com.alibaba.qlexpress4.Express4Runner;
+import com.alibaba.qlexpress4.InitOptions;
+import com.alibaba.qlexpress4.aparser.InterpolationMode;
+import com.alibaba.qlexpress4.security.QLSecurityStrategy;
import com.yomahub.liteflow.builder.el.operator.*;
import com.yomahub.liteflow.common.ChainConstant;
@@ -14,58 +17,72 @@ public class QlExpressUtils {
/**
* EL解析引擎
+ * InterpolationMode.DISABLE意思是不对插值表达式进行处理
*/
- private final static ExpressRunner EXPRESS_RUNNER = new ExpressRunner();
+ private final static Express4Runner EXPRESS_RUNNER = new Express4Runner(InitOptions.builder().interpolationMode(InterpolationMode.DISABLE).build());
+
+ /**
+ * 上下文搜索解析引擎
+ * QLSecurityStrategy.open()意思是将安全策略设置为开放
+ */
+ private final static Express4Runner CONTEXT_SEARCH_EXPRESS_RUNNER = new Express4Runner(InitOptions.builder().securityStrategy(QLSecurityStrategy.open()).build());
static {
// 初始化QLExpress的Runner
- EXPRESS_RUNNER.addFunction(ChainConstant.THEN, new ThenOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.WHEN, new WhenOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.SER, new ThenOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.PAR, new WhenOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.SWITCH, new SwitchOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.PRE, new PreOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.FINALLY, new FinallyOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.IF, new IfOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.NODE.toUpperCase(), new NodeOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.NODE, new NodeOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.FOR, new ForOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.WHILE, new WhileOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.ITERATOR, new IteratorOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.CATCH, new CatchOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.AND, new AndOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.OR, new OrOperator());
- EXPRESS_RUNNER.addFunction(ChainConstant.NOT, new NotOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.ELSE, Object.class, new ElseOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.ELIF, Object.class, new ElifOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.TO, Object.class, new ToOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.TO.toLowerCase(), Object.class, new ToOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.DEFAULT, Object.class, new DefaultOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.TAG, Object.class, new TagOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.ANY, Object.class, new AnyOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.MUST, Object.class, new MustOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.PERCENTAGE, Object.class, new PercentageOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.ID, Object.class, new IdOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.IGNORE_ERROR, Object.class, new IgnoreErrorOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.THREAD_POOL, Object.class, new ThreadPoolOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.DO, Object.class, new DoOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.BREAK, Object.class, new BreakOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.DATA, Object.class, new DataOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.MAX_WAIT_SECONDS, Object.class, new MaxWaitSecondsOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.MAX_WAIT_MILLISECONDS, Object.class, new MaxWaitMillisecondsOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.PARALLEL, Object.class, new ParallelOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.RETRY, Object.class, new RetryOperator());
- EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.BIND, Object.class, new BindOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.THEN, new ThenOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.WHEN, new WhenOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.SER, new ThenOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.PAR, new WhenOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.SWITCH, new SwitchOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.PRE, new PreOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.FINALLY, new FinallyOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.IF, new IfOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.NODE.toUpperCase(), new NodeOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.NODE, new NodeOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.FOR, new ForOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.WHILE, new WhileOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.ITERATOR, new IteratorOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.CATCH, new CatchOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.AND, new AndOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.OR, new OrOperator());
+ EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.NOT, new NotOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.ELSE, Object.class, new ElseOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.ELIF, Object.class, new ElifOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.TO, Object.class, new ToOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.TO.toLowerCase(), Object.class, new ToOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.DEFAULT, Object.class, new DefaultOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.TAG, Object.class, new TagOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.ANY, Object.class, new AnyOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.MUST, Object.class, new MustOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.PERCENTAGE, Object.class, new PercentageOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.ID, Object.class, new IdOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.IGNORE_ERROR, Object.class, new IgnoreErrorOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.THREAD_POOL, Object.class, new ThreadPoolOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.DO, Object.class, new DoOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.BREAK, Object.class, new BreakOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.DATA, Object.class, new DataOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.MAX_WAIT_SECONDS, Object.class, new MaxWaitSecondsOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.MAX_WAIT_MILLISECONDS, Object.class, new MaxWaitMillisecondsOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.PARALLEL, Object.class, new ParallelOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.RETRY, Object.class, new RetryOperator());
+ EXPRESS_RUNNER.addExtendFunction(ChainConstant.BIND, Object.class, new BindOperator());
}
/**
* 获取QLExpress的实例
*/
- public static ExpressRunner getInstance() {
+ public static Express4Runner getELExpressRunner() {
return EXPRESS_RUNNER;
}
+ /**
+ * 获取上下文搜索的QLExpress实例
+ */
+ public static Express4Runner getContextSearchExpressRunner() {
+ return CONTEXT_SEARCH_EXPRESS_RUNNER;
+ }
+
/**
* 检查变量名是否符合 变量命名规则
*
diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/InstanceIdRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/InstanceIdRead.java
index 3aa48f3f4..866898819 100644
--- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/InstanceIdRead.java
+++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/InstanceIdRead.java
@@ -7,7 +7,6 @@ import com.yomahub.liteflow.parser.sql.exception.ELSQLException;
import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead;
import com.yomahub.liteflow.parser.sql.read.vo.InstanceIdVO;
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
-import org.apache.commons.lang.StringUtils;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -59,7 +58,7 @@ public class InstanceIdRead extends AbstractSqlRead {
String instanceIdApplicationNameField = super.config.getInstanceIdApplicationNameField();
String applicationName = super.config.getApplicationName();
- if (StringUtils.isEmpty(chainId)) {
+ if (StrUtil.isEmpty(chainId)) {
throw new IllegalArgumentException("You did not define the chainId");
}
return StrUtil.format(SqlReadConstant.SQL_PATTERN_WITH_CHAIN_ID, tableName, instanceIdApplicationNameField
diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java
index 7d9d474d2..d88051f6b 100644
--- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java
+++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java
@@ -8,7 +8,6 @@ import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead;
import com.yomahub.liteflow.parser.sql.read.vo.ScriptVO;
import com.yomahub.liteflow.parser.sql.util.LiteFlowJdbcUtil;
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
-import org.apache.commons.lang.StringUtils;
import java.sql.Connection;
import java.sql.ResultSet;
@@ -56,7 +55,7 @@ public class ScriptRead extends AbstractSqlRead {
@Override
public String buildQuerySql() {
- if (StringUtils.isNotBlank(super.config.getScriptCustomSql())) {
+ if (StrUtil.isNotBlank(super.config.getScriptCustomSql())) {
return super.config.getScriptCustomSql();
}
@@ -72,7 +71,7 @@ public class ScriptRead extends AbstractSqlRead {
@Override
public String buildQuerySql(String scriptNodeId) {
- if (StringUtils.isNotBlank(super.config.getScriptCustomSql())) {
+ if (StrUtil.isNotBlank(super.config.getScriptCustomSql())) {
return super.config.getScriptCustomSql();
}
diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java
index 0594cf076..3b514d002 100644
--- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java
+++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java
@@ -16,7 +16,6 @@ import com.yomahub.liteflow.parser.sql.read.SqlReadFactory;
import com.yomahub.liteflow.parser.sql.read.vo.ChainVO;
import com.yomahub.liteflow.parser.sql.read.vo.ScriptVO;
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
-import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -116,7 +115,7 @@ public class JDBCHelper {
String language = scriptVO.getLanguage();
String elData = scriptVO.getScript();
- if (StringUtils.isNotBlank(scriptVO.getLanguage())) {
+ if (StrUtil.isNotBlank(scriptVO.getLanguage())) {
scriptList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, language, elData));
} else {
scriptList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, elData));
diff --git a/liteflow-script-plugin/liteflow-script-qlexpress/pom.xml b/liteflow-script-plugin/liteflow-script-qlexpress/pom.xml
index 7580d4316..2708be582 100644
--- a/liteflow-script-plugin/liteflow-script-qlexpress/pom.xml
+++ b/liteflow-script-plugin/liteflow-script-qlexpress/pom.xml
@@ -23,7 +23,7 @@
com.alibaba
- QLExpress
+ qlexpress4
\ No newline at end of file
diff --git a/liteflow-script-plugin/liteflow-script-qlexpress/src/main/java/com/yomahub/liteflow/script/qlexpress/QLExpressScriptExecutor.java b/liteflow-script-plugin/liteflow-script-qlexpress/src/main/java/com/yomahub/liteflow/script/qlexpress/QLExpressScriptExecutor.java
index 66a86beac..c0150d87b 100644
--- a/liteflow-script-plugin/liteflow-script-qlexpress/src/main/java/com/yomahub/liteflow/script/qlexpress/QLExpressScriptExecutor.java
+++ b/liteflow-script-plugin/liteflow-script-qlexpress/src/main/java/com/yomahub/liteflow/script/qlexpress/QLExpressScriptExecutor.java
@@ -1,11 +1,11 @@
package com.yomahub.liteflow.script.qlexpress;
-import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
-import com.ql.util.express.DefaultContext;
-import com.ql.util.express.ExpressLoader;
-import com.ql.util.express.ExpressRunner;
-import com.ql.util.express.InstructionSet;
+import com.alibaba.qlexpress4.Express4Runner;
+import com.alibaba.qlexpress4.QLResult;
+import com.alibaba.qlexpress4.InitOptions;
+import com.alibaba.qlexpress4.QLOptions;
+import com.alibaba.qlexpress4.security.QLSecurityStrategy;
import com.yomahub.liteflow.enums.ScriptTypeEnum;
import com.yomahub.liteflow.script.ScriptExecuteWrap;
import com.yomahub.liteflow.script.ScriptExecutor;
@@ -13,10 +13,8 @@ import com.yomahub.liteflow.script.exception.ScriptLoadException;
import com.yomahub.liteflow.util.CopyOnWriteHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-import javax.script.ScriptException;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -30,13 +28,13 @@ public class QLExpressScriptExecutor extends ScriptExecutor {
private final Logger log = LoggerFactory.getLogger(this.getClass());
- private ExpressRunner expressRunner;
+ private Express4Runner expressRunner;
- private final Map compiledScriptMap = new CopyOnWriteHashMap<>();
+ private final Map compiledScriptMap = new CopyOnWriteHashMap<>();
@Override
public ScriptExecutor init() {
- expressRunner = new ExpressRunner(true, false);
+ expressRunner = new Express4Runner(InitOptions.builder().securityStrategy(QLSecurityStrategy.open()).build());
//如果有生命周期则执行相应生命周期实现
super.lifeCycle(expressRunner);
return this;
@@ -45,7 +43,8 @@ public class QLExpressScriptExecutor extends ScriptExecutor {
@Override
public void load(String nodeId, String script) {
try {
- compiledScriptMap.put(nodeId, (InstructionSet) compile(script));
+ expressRunner.parseToDefinitionWithCache(script);
+ compiledScriptMap.put(nodeId, script);
}
catch (Exception e) {
String errorMsg = StrUtil.format("script loading error for node[{}],error msg:{}", nodeId, e.getMessage());
@@ -65,24 +64,21 @@ public class QLExpressScriptExecutor extends ScriptExecutor {
@Override
public Object executeScript(ScriptExecuteWrap wrap) throws Exception {
- List errorList = new ArrayList<>();
try {
if (!compiledScriptMap.containsKey(wrap.getNodeId())) {
String errorMsg = StrUtil.format("script for node[{}] is not loaded", wrap.getNodeId());
throw new ScriptLoadException(errorMsg);
}
- InstructionSet instructionSet = compiledScriptMap.get(wrap.getNodeId());
- DefaultContext context = new DefaultContext<>();
+ String script = compiledScriptMap.get(wrap.getNodeId());
+ Map context = new HashMap<>();
bindParam(wrap, context::put, context::putIfAbsent);
- return expressRunner.execute(instructionSet, context, errorList, true, false);
+ QLResult expressResult = expressRunner.execute(script, context, QLOptions.builder().cache(true).build());
+ return expressResult.getResult();
}
catch (Exception e) {
- for (String scriptErrorMsg : errorList) {
- log.error("\n{}", scriptErrorMsg);
- }
throw e;
}
}
@@ -90,8 +86,9 @@ public class QLExpressScriptExecutor extends ScriptExecutor {
@Override
public void cleanCache() {
compiledScriptMap.clear();
- expressRunner.clearExpressCache();
- ReflectUtil.setFieldValue(expressRunner, "loader", new ExpressLoader(expressRunner));
+ expressRunner.clearCompileCache();
+ //如果有生命周期则执行相应生命周期实现
+ super.lifeCycle(expressRunner);
}
@Override
@@ -101,7 +98,7 @@ public class QLExpressScriptExecutor extends ScriptExecutor {
@Override
public Object compile(String script) throws Exception {
- return expressRunner.getInstructionSetFromLocalCache(script);
+ return expressRunner.parseToDefinitionWithCache(script);
}
}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/parent/ParentDeclMultiSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/parent/ParentDeclMultiSpringbootTest.java
new file mode 100644
index 000000000..f4b58b558
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/parent/ParentDeclMultiSpringbootTest.java
@@ -0,0 +1,38 @@
+package com.yomahub.liteflow.test.parent;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.annotation.Resource;
+
+/**
+ * springboot环境最普通的例子测试
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+@ExtendWith(SpringExtension.class)
+@TestPropertySource(value = "classpath:/parent/application.properties")
+@SpringBootTest(classes = ParentDeclMultiSpringbootTest.class)
+@EnableAutoConfiguration
+@ComponentScan({ "com.yomahub.liteflow.test.parent.cmp" })
+public class ParentDeclMultiSpringbootTest extends BaseTest {
+
+ @Resource
+ private FlowExecutor flowExecutor;
+
+ @Test
+ public void testP1() throws Exception {
+ LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+ Assertions.assertTrue(response.isSuccess());
+ }
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/parent/cmp/CmpConfig.java b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/parent/cmp/CmpConfig.java
new file mode 100644
index 000000000..ef686a6b5
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/parent/cmp/CmpConfig.java
@@ -0,0 +1,31 @@
+package com.yomahub.liteflow.test.parent.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.test.base.cmp.TestDomain;
+
+import javax.annotation.Resource;
+
+@LiteflowComponent
+public class CmpConfig extends ParentClass{
+
+ @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+ public void processA(NodeComponent bindCmp) {
+ this.setName("jack");
+ System.out.println(this.sayHi());
+ }
+
+ @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+ public void processB(NodeComponent bindCmp) {
+ this.setName("tom");
+ System.out.println(this.sayHi());
+ }
+
+ @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+ public void processC(NodeComponent bindCmp) {
+ this.setName("jerry");
+ System.out.println(this.sayHi());
+ }
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/parent/cmp/ParentClass.java b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/parent/cmp/ParentClass.java
new file mode 100644
index 000000000..322689371
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/parent/cmp/ParentClass.java
@@ -0,0 +1,14 @@
+package com.yomahub.liteflow.test.parent.cmp;
+
+public class ParentClass {
+
+ private String name;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String sayHi() {
+ return "hello " + name;
+ }
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/parent/application.properties b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/parent/application.properties
new file mode 100644
index 000000000..03350a714
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/parent/application.properties
@@ -0,0 +1 @@
+liteflow.rule-source=parent/flow.el.xml
\ No newline at end of file
diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/parent/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/parent/flow.el.xml
new file mode 100644
index 000000000..98c3cbae6
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/parent/flow.el.xml
@@ -0,0 +1,7 @@
+
+
+
+ THEN(a, b, c);
+
+
+
\ No newline at end of file
diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/base/BaseELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/base/BaseELSpringbootTest.java
index 4e600df2a..e2803f0f1 100644
--- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/base/BaseELSpringbootTest.java
+++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/base/BaseELSpringbootTest.java
@@ -97,8 +97,17 @@ public class BaseELSpringbootTest extends BaseTest {
// 应返回 chain2
Assertions.assertEquals("chain2", response.getChainId());
- LiteflowResponse response1 = flowExecutor.execute2RespWithEL("t1=THEN(c, WHEN(j,k));w1 = WHEN(q, THEN(p, r)).id('w01');t2 = THEN(h, i);\n" +
- "THEN(a,b,WHEN(t1, d, t2 ),SWITCH(x).to(m, n, w1),z);");
+ LiteflowResponse response1 = flowExecutor.execute2RespWithEL("t1 = THEN(c, WHEN(j,k));\n" +
+ " w1 = WHEN(q, THEN(p, r)).id(\"w01\");\n" +
+ " t2 = THEN(h, i);\n" +
+ "\n" +
+ " THEN(\n" +
+ " a,b,\n" +
+ " WHEN(t1, d, t2 ),\n" +
+ " SWITCH(x).to(m, n, w1),\n" +
+ " z\n" +
+ " );\n" +
+ " THEN(a,b,b,a,SWITCH(e).TO(d,b));");
Assertions.assertTrue(response1.isSuccess());
// 应返回 chain5
Assertions.assertEquals("chain5", response1.getChainId());
diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/base/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/base/flow.el.xml
index aab117311..2e5c582d4 100644
--- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/base/flow.el.xml
+++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/base/flow.el.xml
@@ -50,5 +50,7 @@
SWITCH(x).to(m, n, w1),
z
);
+ THEN(a,b,b,a,SWITCH(e).TO(d,b))
-
\ No newline at end of file
+
+
diff --git a/pom.xml b/pom.xml
index 55a54b112..76f8fce6a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,7 +39,7 @@
- 2.15.1
+ 2.15.2
UTF-8
UTF-8
8
@@ -58,7 +58,7 @@
0.10
0.7.3
1.4.4
- 3.3.4
+ 4.0.6-SNAPSHOT
3.0.25
22.0.0
1.17.7
@@ -227,7 +227,7 @@
com.alibaba
- QLExpress
+ qlexpress4
${qlexpress.version}