mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-05-19 18:18:09 +08:00
Merge branch 'qlexpress4' into dev
# Conflicts: # .gitignore
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -81,6 +81,5 @@ atlassian-ide-plugin.xml
|
||||
*/logs
|
||||
|
||||
.flattened-pom.xml
|
||||
|
||||
.claude
|
||||
.vscode
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-script-javax-pro</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>${liteflow-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-script-javax</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>${liteflow-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,6 @@
|
||||
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
THEN(a);
|
||||
THEN(a,b,c);
|
||||
</chain>
|
||||
</flow>
|
||||
16
liteflow-benchmark/liteflow-benchmark-compile/pom.xml
Normal file
16
liteflow-benchmark/liteflow-benchmark-compile/pom.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>liteflow-benchmark</artifactId>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>liteflow-benchmark-compile</artifactId>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -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()));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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<QueryVO> queryList = context.getQueryResultList();
|
||||
|
||||
//选择渠道余量最大的
|
||||
QueryVO vo = queryList.stream().min((o1, o2) -> o2.getAvailCount() - o1.getAvailCount()).orElse(null);
|
||||
|
||||
assert vo != null;
|
||||
context.setFinalResultChannel(vo.getChannel());
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
@@ -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<QueryVO> queryResultList;
|
||||
|
||||
private String finalResultChannel;
|
||||
|
||||
public List<QueryVO> getQueryResultList() {
|
||||
return queryResultList;
|
||||
}
|
||||
|
||||
public void setQueryResultList(List<QueryVO> 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
liteflow.rule-source=flow.xml
|
||||
liteflow.fast-load=true
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<chain name="channelSenderChain">
|
||||
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);
|
||||
</chain>
|
||||
</flow>
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-script-groovy</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>${liteflow-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-script-java</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>${liteflow-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-script-javax-pro</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>${liteflow-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-script-javax</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>${liteflow-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
|
||||
<properties>
|
||||
<jmh.version>1.37</jmh.version>
|
||||
<liteflow-version>${revision}</liteflow-version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-spring-boot-starter</artifactId>
|
||||
<version>${revision}</version>
|
||||
<version>${liteflow-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -48,5 +49,6 @@
|
||||
<module>liteflow-benchmark-script-groovy</module>
|
||||
<module>liteflow-benchmark-common</module>
|
||||
<module>liteflow-benchmark-common-example</module>
|
||||
<module>liteflow-benchmark-compile</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -54,7 +54,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>QLExpress</artifactId>
|
||||
<artifactId>qlexpress4</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
|
||||
@@ -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<String> outVarNames = EXPRESS_RUNNER.getOutVarNames(elStr);
|
||||
if (CollUtil.isEmpty(outVarNames)) {
|
||||
return msg;
|
||||
}
|
||||
|
||||
List<String> chainIds = CollUtil.map(FlowBus.getChainMap().values(), Chain::getChainId, true);
|
||||
List<String> 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<String> errorList = new ArrayList<>();
|
||||
try {
|
||||
DefaultContext<String, Object> context = new DefaultContext<>();
|
||||
Map<String, Object> 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<String> 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 = (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 extends Executable> T compile(String elStr, List<String> errorList, boolean putChain2Context) throws Exception{
|
||||
DefaultContext<String, Object> context = new DefaultContext<>();
|
||||
Map<String, Object> context = new HashMap<>();
|
||||
|
||||
if (putChain2Context){
|
||||
// 这里一定要先放chain,再放node,因为node优先于chain,所以当重名时,node会覆盖掉chain
|
||||
@@ -431,8 +431,8 @@ public class LiteFlowChainELBuilder {
|
||||
// 解析el成为一个Condition
|
||||
// 为什么这里只是一个Condition,而不是一个List<Condition>呢
|
||||
// 这里无论多复杂的,外面必定有一个最外层的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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Condition> {
|
||||
}
|
||||
else {
|
||||
String errorMsg = "The caller must be LoopCondition or CatchCondition item";
|
||||
throw new QLException(errorMsg);
|
||||
throw new ELParseException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<ForCondition> {
|
||||
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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<Condition> {
|
||||
} 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);
|
||||
|
||||
@@ -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<WhenCondition> {
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<Condition> {
|
||||
return condition;
|
||||
} else {
|
||||
String errorMsg = "The caller must be WhenCondition or LoopCondition item";
|
||||
throw new QLException(errorMsg);
|
||||
throw new ELParseException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<T extends Executable> extends Operator {
|
||||
public abstract class BaseOperator<T extends Executable> 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;
|
||||
|
||||
@@ -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> T convert(Object object, Class<T> clazz) throws QLException {
|
||||
public static <T> T convert(Object object, Class<T> 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> T convert(Object object, Class<T> clazz, String errorMsg) throws QLException {
|
||||
public static <T> T convert(Object object, Class<T> 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<String> 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格式信息
|
||||
|
||||
@@ -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<String> 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<InstanceInfoDto> 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);
|
||||
|
||||
@@ -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<Tuple> contextList, String regPattern){
|
||||
// 把上下文数据转换成map形式的,key为别名,value为上下文
|
||||
@@ -34,16 +36,14 @@ public class LiteflowContextRegexMatcher {
|
||||
Collectors.toMap(tuple -> tuple.get(0), tuple -> tuple.get(1))
|
||||
);
|
||||
|
||||
List<String> errorList = new ArrayList<>();
|
||||
|
||||
Object result = null;
|
||||
// 根据表达式去上下文里搜索相匹配的数据
|
||||
for(Map.Entry<String, Object> entry : contextMap.entrySet()){
|
||||
try{
|
||||
InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache(entry.getKey() + "." + regPattern);
|
||||
DefaultContext<String, Object> context = new DefaultContext<>();
|
||||
Map<String, Object> 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<String, Object> context = new DefaultContext<>();
|
||||
Map<String, Object> 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<String> errorList = new ArrayList<>();
|
||||
|
||||
boolean flag = false;
|
||||
|
||||
String argStr = IntStream.range(0, args.length).mapToObj(
|
||||
@@ -83,11 +81,10 @@ public class LiteflowContextRegexMatcher {
|
||||
|
||||
for(Map.Entry<String, Object> entry : contextMap.entrySet()){
|
||||
try{
|
||||
InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache(StrUtil.format("{}.{}({})", entry.getKey(), methodExpress, argStr));
|
||||
DefaultContext<String, Object> context = new DefaultContext<>();
|
||||
Map<String, Object> 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<String, Object> context = new DefaultContext<>();
|
||||
Map<String, Object> 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){}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查变量名是否符合 变量命名规则
|
||||
*
|
||||
|
||||
@@ -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<InstanceIdVO> {
|
||||
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
|
||||
|
||||
@@ -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<ScriptVO> {
|
||||
|
||||
@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<ScriptVO> {
|
||||
|
||||
@Override
|
||||
public String buildQuerySql(String scriptNodeId) {
|
||||
if (StringUtils.isNotBlank(super.config.getScriptCustomSql())) {
|
||||
if (StrUtil.isNotBlank(super.config.getScriptCustomSql())) {
|
||||
return super.config.getScriptCustomSql();
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>QLExpress</artifactId>
|
||||
<artifactId>qlexpress4</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -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<String, InstructionSet> compiledScriptMap = new CopyOnWriteHashMap<>();
|
||||
private final Map<String, String> 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<String> 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<String, Object> context = new DefaultContext<>();
|
||||
String script = compiledScriptMap.get(wrap.getNodeId());
|
||||
Map<String, Object> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
liteflow.rule-source=parent/flow.el.xml
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
THEN(a, b, c);
|
||||
</chain>
|
||||
|
||||
</flow>
|
||||
@@ -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());
|
||||
|
||||
@@ -50,5 +50,7 @@
|
||||
SWITCH(x).to(m, n, w1),
|
||||
z
|
||||
);
|
||||
THEN(a,b,b,a,SWITCH(e).TO(d,b))
|
||||
</chain>
|
||||
</flow>
|
||||
|
||||
</flow>
|
||||
|
||||
6
pom.xml
6
pom.xml
@@ -39,7 +39,7 @@
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<revision>2.15.1</revision>
|
||||
<revision>2.15.2</revision>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
@@ -58,7 +58,7 @@
|
||||
<zkclient.version>0.10</zkclient.version>
|
||||
<jetcd.version>0.7.3</jetcd.version>
|
||||
<nacos.version>1.4.4</nacos.version>
|
||||
<qlexpress.version>3.3.4</qlexpress.version>
|
||||
<qlexpress.version>4.0.6-SNAPSHOT</qlexpress.version>
|
||||
<groovy.version>3.0.25</groovy.version>
|
||||
<graalvm.version>22.0.0</graalvm.version>
|
||||
<bytebuddy.version>1.17.7</bytebuddy.version>
|
||||
@@ -227,7 +227,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>QLExpress</artifactId>
|
||||
<artifactId>qlexpress4</artifactId>
|
||||
<version>${qlexpress.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
Reference in New Issue
Block a user