feature #I9PVQ7 决策路由中增加namespace,可以执行指定命名空间的决策路由
This commit is contained in:
parent
1dbcc9bba7
commit
c8062d6585
|
@ -233,6 +233,11 @@ public class LiteFlowChainELBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
public LiteFlowChainELBuilder setNamespace(String nameSpace){
|
||||
this.chain.setNamespace(nameSpace);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* EL表达式校验
|
||||
* @param elStr EL表达式
|
||||
|
|
|
@ -32,6 +32,10 @@ public interface ChainConstant {
|
|||
|
||||
String LANGUAGE = "language";
|
||||
|
||||
String NAMESPACE = "namespace";
|
||||
|
||||
String DEFAULT_NAMESPACE = "default";
|
||||
|
||||
String VALUE = "value";
|
||||
|
||||
String ANY = "any";
|
||||
|
|
|
@ -13,6 +13,7 @@ import cn.hutool.core.collection.ListUtil;
|
|||
import cn.hutool.core.lang.Tuple;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.*;
|
||||
import com.yomahub.liteflow.common.ChainConstant;
|
||||
import com.yomahub.liteflow.enums.ChainExecuteModeEnum;
|
||||
import com.yomahub.liteflow.enums.InnerChainTypeEnum;
|
||||
import com.yomahub.liteflow.enums.ParseModeEnum;
|
||||
|
@ -283,7 +284,11 @@ public class FlowExecutor {
|
|||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChain(Object param, Class<?>... contextBeanClazzArray){
|
||||
return this.executeWithRoute(param, null, contextBeanClazzArray, null);
|
||||
return this.executeWithRoute(null, param, null, contextBeanClazzArray, null);
|
||||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChain(String namespace, Object param, Class<?>... contextBeanClazzArray){
|
||||
return this.executeWithRoute(namespace, param, null, contextBeanClazzArray, null);
|
||||
}
|
||||
|
||||
public LiteflowResponse execute2Resp(String chainId, Object param, Object... contextBeanArray) {
|
||||
|
@ -291,23 +296,35 @@ public class FlowExecutor {
|
|||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChain(Object param, Object... contextBeanArray){
|
||||
return this.executeWithRoute(param, null, null, contextBeanArray);
|
||||
return this.executeWithRoute(null, param, null, null, contextBeanArray);
|
||||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChain(String namespace, Object param, Object... contextBeanArray){
|
||||
return this.executeWithRoute(namespace, param, null, null, contextBeanArray);
|
||||
}
|
||||
|
||||
public LiteflowResponse execute2RespWithRid(String chainId, Object param, String requestId, Class<?>... contextBeanClazzArray) {
|
||||
return this.execute2Resp(chainId, param, requestId, contextBeanClazzArray, null);
|
||||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChainWithRid(String chainId, Object param, String requestId, Class<?>... contextBeanClazzArray) {
|
||||
return this.executeWithRoute(param, requestId, contextBeanClazzArray, null);
|
||||
public List<LiteflowResponse> executeRouteChainWithRid(Object param, String requestId, Class<?>... contextBeanClazzArray) {
|
||||
return this.executeWithRoute(null, param, requestId, contextBeanClazzArray, null);
|
||||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChainWithRid(String namespace, Object param, String requestId, Class<?>... contextBeanClazzArray) {
|
||||
return this.executeWithRoute(namespace, param, requestId, contextBeanClazzArray, null);
|
||||
}
|
||||
|
||||
public LiteflowResponse execute2RespWithRid(String chainId, Object param, String requestId, Object... contextBeanArray) {
|
||||
return this.execute2Resp(chainId, param, requestId, null, contextBeanArray);
|
||||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChainWithRid(String chainId, Object param, String requestId, Object... contextBeanArray) {
|
||||
return this.executeWithRoute(param, requestId, null, contextBeanArray);
|
||||
public List<LiteflowResponse> executeRouteChainWithRid(Object param, String requestId, Object... contextBeanArray) {
|
||||
return this.executeWithRoute(null, param, requestId, null, contextBeanArray);
|
||||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChainWithRid(String namespace, Object param, String requestId, Object... contextBeanArray) {
|
||||
return this.executeWithRoute(namespace, param, requestId, null, contextBeanArray);
|
||||
}
|
||||
|
||||
// 调用一个流程并返回Future<LiteflowResponse>,允许多上下文的传入
|
||||
|
@ -353,8 +370,8 @@ public class FlowExecutor {
|
|||
return LiteflowResponse.newMainResponse(slot);
|
||||
}
|
||||
|
||||
private List<LiteflowResponse> executeWithRoute(Object param, String requestId, Class<?>[] contextBeanClazzArray, Object[] contextBeanArray){
|
||||
List<Slot> slotList = doExecuteWithRoute(param, requestId, contextBeanClazzArray, contextBeanArray);
|
||||
private List<LiteflowResponse> executeWithRoute(String namespace, Object param, String requestId, Class<?>[] contextBeanClazzArray, Object[] contextBeanArray){
|
||||
List<Slot> slotList = doExecuteWithRoute(namespace, param, requestId, contextBeanClazzArray, contextBeanArray);
|
||||
return slotList.stream().map(LiteflowResponse::newMainResponse).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
@ -522,15 +539,23 @@ public class FlowExecutor {
|
|||
MonitorFile.getInstance().addMonitorFilePaths(fileAbsolutePath);
|
||||
}
|
||||
|
||||
private List<Slot> doExecuteWithRoute(Object param, String requestId, Class<?>[] contextBeanClazzArray, Object[] contextBeanArray){
|
||||
private List<Slot> doExecuteWithRoute(String namespace, Object param, String requestId, Class<?>[] contextBeanClazzArray, Object[] contextBeanArray){
|
||||
if (FlowBus.needInit()) {
|
||||
init(true);
|
||||
}
|
||||
|
||||
List<Chain> routeChainList = FlowBus.getChainMap().values().stream().filter(chain -> chain.getRouteItem() != null).collect(Collectors.toList());
|
||||
if (StrUtil.isBlank(namespace)){
|
||||
namespace = ChainConstant.DEFAULT_NAMESPACE;
|
||||
}
|
||||
|
||||
String finalNamespace = namespace;
|
||||
List<Chain> routeChainList = FlowBus.getChainMap().values().stream()
|
||||
.filter(chain -> chain.getNamespace().equals(finalNamespace))
|
||||
.filter(chain -> chain.getRouteItem() != null).collect(Collectors.toList());
|
||||
|
||||
if (CollUtil.isEmpty(routeChainList)){
|
||||
throw new RouteChainNotFoundException("cannot find any route chain");
|
||||
String errorMsg = StrUtil.format("no route found for namespace[{}]", finalNamespace);
|
||||
throw new RouteChainNotFoundException(errorMsg);
|
||||
}
|
||||
|
||||
String finalRequestId;
|
||||
|
@ -601,7 +626,7 @@ public class FlowExecutor {
|
|||
}
|
||||
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
|
||||
LOG.info("There are {} chains that matched the route.", resultSlotList.size());
|
||||
LOG.info("chain namespace:[{}], total size:[{}], matched size:[{}]", namespace, routeChainList.size(), resultSlotList.size());
|
||||
|
||||
return resultSlotList;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@ public class Chain implements Executable{
|
|||
|
||||
private boolean isCompiled = true;
|
||||
|
||||
private String namespace;
|
||||
|
||||
public Chain(String chainName) {
|
||||
this.chainId = chainName;
|
||||
}
|
||||
|
@ -195,4 +197,12 @@ public class Chain implements Executable{
|
|||
public void setCompiled(boolean compiled) {
|
||||
isCompiled = compiled;
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.yomahub.liteflow.parser.helper;
|
||||
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
@ -24,6 +25,7 @@ import java.util.Map;
|
|||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static com.yomahub.liteflow.common.ChainConstant.*;
|
||||
|
||||
|
@ -310,9 +312,11 @@ public class ParserHelper {
|
|||
// 构建chainBuilder
|
||||
String chainId = Optional.ofNullable(chainNode.get(ID)).orElse(chainNode.get(NAME)).textValue();
|
||||
|
||||
String namespace = chainNode.get(NAMESPACE) == null? DEFAULT_NAMESPACE : chainNode.get(NAMESPACE).textValue();
|
||||
|
||||
JsonNode routeJsonNode = chainNode.get(ROUTE);
|
||||
|
||||
LiteFlowChainELBuilder builder = LiteFlowChainELBuilder.createChain().setChainId(chainId);
|
||||
LiteFlowChainELBuilder builder = LiteFlowChainELBuilder.createChain().setChainId(chainId).setNamespace(namespace);
|
||||
|
||||
// 如果有route这个标签,说明是决策表chain
|
||||
// 决策表链路必须有route和body这两个标签
|
||||
|
@ -339,9 +343,11 @@ public class ParserHelper {
|
|||
// 构建chainBuilder
|
||||
String chainId = Optional.ofNullable(e.attributeValue(ID)).orElse(e.attributeValue(NAME));
|
||||
|
||||
String namespace = StrUtil.blankToDefault(e.attributeValue(NAMESPACE), DEFAULT_NAMESPACE);
|
||||
|
||||
Element routeElement = e.element(ROUTE);
|
||||
|
||||
LiteFlowChainELBuilder builder = LiteFlowChainELBuilder.createChain().setChainId(chainId);
|
||||
LiteFlowChainELBuilder builder = LiteFlowChainELBuilder.createChain().setChainId(chainId).setNamespace(namespace);
|
||||
|
||||
// 如果有route这个标签,说明是决策表chain
|
||||
// 决策表链路必须有route和body这两个标签
|
||||
|
@ -364,6 +370,7 @@ public class ParserHelper {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
builder.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,9 +14,12 @@
|
|||
class CDATA #IMPLIED
|
||||
file CDATA #IMPLIED
|
||||
language (qlexpress|groovy|js|python|lua|aviator|java) #IMPLIED
|
||||
enable (true|false) #IMPLIED
|
||||
>
|
||||
<!ATTLIST chain
|
||||
id CDATA #IMPLIED
|
||||
name CDATA #IMPLIED
|
||||
extends CDATA #IMPLIED
|
||||
enable (true|false) #IMPLIED
|
||||
namespace CDATA #IMPLIED
|
||||
>
|
|
@ -0,0 +1,66 @@
|
|||
package com.yomahub.liteflow.test.namespace;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.exception.NoMatchedRouteChainException;
|
||||
import com.yomahub.liteflow.exception.RouteChainNotFoundException;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
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 javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* springboot环境EL常规的例子测试
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
*/
|
||||
@TestPropertySource(value = "classpath:/namespace/application.properties")
|
||||
@SpringBootTest(classes = RouteSpringbootNamespaceTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({ "com.yomahub.liteflow.test.namespace.cmp" })
|
||||
public class RouteSpringbootNamespaceTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
// n1 space中的两个链路都能匹配
|
||||
@Test
|
||||
public void testNamespaceRoute1() throws Exception {
|
||||
List<LiteflowResponse> responseList = flowExecutor.executeRouteChain("n1", 15, DefaultContext.class);
|
||||
LiteflowResponse response1 = responseList.stream().filter(
|
||||
liteflowResponse -> liteflowResponse.getChainId().equals("r_chain1")
|
||||
).findFirst().orElse(null);
|
||||
|
||||
assert response1 != null;
|
||||
Assertions.assertTrue(response1.isSuccess());
|
||||
Assertions.assertEquals("b==>a", response1.getExecuteStepStr());
|
||||
|
||||
LiteflowResponse response2 = responseList.stream().filter(
|
||||
liteflowResponse -> liteflowResponse.getChainId().equals("r_chain2")
|
||||
).findFirst().orElse(null);
|
||||
|
||||
assert response2 != null;
|
||||
Assertions.assertTrue(response2.isSuccess());
|
||||
Assertions.assertEquals("a==>b", response2.getExecuteStepStr());
|
||||
}
|
||||
|
||||
// n1这个namespace中没有规则被匹配上
|
||||
@Test
|
||||
public void testNamespaceRoute2() throws Exception {
|
||||
Assertions.assertThrows(NoMatchedRouteChainException.class, () -> flowExecutor.executeRouteChain("n1", 8, DefaultContext.class));
|
||||
}
|
||||
|
||||
// 没有n3这个namespace
|
||||
@Test
|
||||
public void testNamespaceRoute3() throws Exception {
|
||||
Assertions.assertThrows(RouteChainNotFoundException.class, () -> flowExecutor.executeRouteChain("n3", 8, DefaultContext.class));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.namespace.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.namespace.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.namespace.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeBooleanComponent;
|
||||
|
||||
@LiteflowComponent("r1")
|
||||
public class R1 extends NodeBooleanComponent {
|
||||
@Override
|
||||
public boolean processBoolean() throws Exception {
|
||||
int testInt = this.getRequestData();
|
||||
return testInt >= 10 && testInt <= 20;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.namespace.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeBooleanComponent;
|
||||
|
||||
@LiteflowComponent("r2")
|
||||
public class R2 extends NodeBooleanComponent {
|
||||
@Override
|
||||
public boolean processBoolean() throws Exception {
|
||||
int testInt = this.getRequestData();
|
||||
return testInt > 100;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
liteflow.rule-source=namespace/flow.el.xml
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
|
||||
<flow>
|
||||
<chain name="r_chain1" namespace="n1">
|
||||
<route>
|
||||
r1
|
||||
</route>
|
||||
<body>
|
||||
THEN(b,a);
|
||||
</body>
|
||||
</chain>
|
||||
|
||||
<chain name="r_chain2" namespace="n1">
|
||||
<route>
|
||||
OR(r1,r2)
|
||||
</route>
|
||||
<body>
|
||||
THEN(a,b);
|
||||
</body>
|
||||
</chain>
|
||||
|
||||
<chain name="r_chain3" namespace="n2">
|
||||
<route>
|
||||
r2
|
||||
</route>
|
||||
<body>
|
||||
THEN(b,b);
|
||||
</body>
|
||||
</chain>
|
||||
</flow>
|
Loading…
Reference in New Issue