mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-05-15 12:32:09 +08:00
@@ -11,8 +11,13 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class LiteFlowNodeBuilder {
|
||||
|
||||
@@ -132,33 +137,16 @@ public class LiteFlowNodeBuilder {
|
||||
public void build() {
|
||||
checkBuild();
|
||||
try {
|
||||
if (this.node.getType().equals(NodeTypeEnum.COMMON)) {
|
||||
FlowBus.addCommonNode(this.node.getId(), this.node.getName(), this.node.getClazz());
|
||||
} else if (this.node.getType().equals(NodeTypeEnum.SWITCH)) {
|
||||
FlowBus.addSwitchNode(this.node.getId(), this.node.getName(), this.node.getClazz());
|
||||
} else if (this.node.getType().equals(NodeTypeEnum.IF)) {
|
||||
FlowBus.addIfNode(this.node.getId(), this.node.getName(), this.node.getClazz());
|
||||
} else if (this.node.getType().equals(NodeTypeEnum.FOR)) {
|
||||
FlowBus.addForNode(this.node.getId(), this.node.getName(), this.node.getClazz());
|
||||
} else if (this.node.getType().equals(NodeTypeEnum.WHILE)) {
|
||||
FlowBus.addWhileNode(this.node.getId(), this.node.getName(), this.node.getClazz());
|
||||
} else if (this.node.getType().equals(NodeTypeEnum.BREAK)) {
|
||||
FlowBus.addBreakNode(this.node.getId(), this.node.getName(), this.node.getClazz());
|
||||
} else if (this.node.getType().equals(NodeTypeEnum.SCRIPT)) {
|
||||
FlowBus.addCommonScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
|
||||
} else if (this.node.getType().equals(NodeTypeEnum.SWITCH_SCRIPT)) {
|
||||
FlowBus.addSwitchScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
|
||||
} else if (this.node.getType().equals(NodeTypeEnum.IF_SCRIPT)) {
|
||||
FlowBus.addIfScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
|
||||
} else if (this.node.getType().equals(NodeTypeEnum.FOR_SCRIPT)) {
|
||||
FlowBus.addForScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
|
||||
} else if (this.node.getType().equals(NodeTypeEnum.WHILE_SCRIPT)) {
|
||||
FlowBus.addWhileScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
|
||||
} else if (this.node.getType().equals(NodeTypeEnum.BREAK_SCRIPT)) {
|
||||
FlowBus.addBreakScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
|
||||
}
|
||||
// 用于处理脚本 node
|
||||
if (this.node.getType().isScript()){
|
||||
FlowBus.addScriptNode(this.node.getId(), this.node.getName(), this.node.getType(), this.node.getScript());
|
||||
}
|
||||
// 用于处理普通 node
|
||||
else{
|
||||
FlowBus.addNode(this.node.getId(), this.node.getName(), this.node.getType(), this.node.getClazz());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
String errMsg = StrUtil.format("An exception occurred while building the node[{}],{}", this.node.getId(),e.getMessage());
|
||||
String errMsg = StrUtil.format("An exception occurred while building the node[{}],{}", this.node.getId(), e.getMessage());
|
||||
LOG.error(errMsg, e);
|
||||
throw new NodeBuildException(errMsg);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,28 @@
|
||||
package com.yomahub.liteflow.core;
|
||||
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 脚本接口
|
||||
* @author Bryan.Zhang
|
||||
* @since 2.9.0
|
||||
*/
|
||||
public interface ScriptComponent {
|
||||
/**
|
||||
* 用于维护脚本类型和脚本 cmp 的映射关系
|
||||
*/
|
||||
Map<NodeTypeEnum, Class<?>> ScriptComponentClassMap = new HashMap<NodeTypeEnum, Class<?>>() {{
|
||||
put(NodeTypeEnum.SCRIPT, ScriptCommonComponent.class);
|
||||
put(NodeTypeEnum.SWITCH_SCRIPT, ScriptSwitchComponent.class);
|
||||
put(NodeTypeEnum.IF_SCRIPT, ScriptIfComponent.class);
|
||||
put(NodeTypeEnum.FOR_SCRIPT, ScriptForComponent.class);
|
||||
put(NodeTypeEnum.WHILE_SCRIPT, ScriptWhileComponent.class);
|
||||
put(NodeTypeEnum.BREAK_SCRIPT, ScriptBreakComponent.class);
|
||||
}};
|
||||
|
||||
|
||||
/**
|
||||
* 加载脚本
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
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;
|
||||
@@ -43,6 +44,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 流程元数据类
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
*/
|
||||
public class FlowBus {
|
||||
@@ -56,13 +58,13 @@ public class FlowBus {
|
||||
private FlowBus() {
|
||||
}
|
||||
|
||||
public static Chain getChain(String id){
|
||||
public static Chain getChain(String id) {
|
||||
return chainMap.get(id);
|
||||
}
|
||||
|
||||
//这一方法主要用于第一阶段chain的预装载
|
||||
public static void addChain(String chainName){
|
||||
if (!chainMap.containsKey(chainName)){
|
||||
public static void addChain(String chainName) {
|
||||
if (!chainMap.containsKey(chainName)) {
|
||||
chainMap.put(chainName, new Chain(chainName));
|
||||
}
|
||||
}
|
||||
@@ -88,119 +90,53 @@ public class FlowBus {
|
||||
//根据class来猜测类型
|
||||
NodeTypeEnum type = NodeTypeEnum.guessType(nodeComponent.getClass());
|
||||
|
||||
if (type == null){
|
||||
if (type == null) {
|
||||
throw new NullNodeTypeException(StrUtil.format("node type is null for node[{}]", nodeId));
|
||||
}
|
||||
|
||||
nodeMap.put(nodeId, new Node(ComponentInitializer.loadInstance().initComponent(nodeComponent, type, null, nodeId)));
|
||||
}
|
||||
|
||||
public static void addCommonNode(String nodeId, String name, String cmpClazzStr){
|
||||
/**
|
||||
* 添加 node
|
||||
*
|
||||
* @param nodeId 节点id
|
||||
* @param name 节点名称
|
||||
* @param type 节点类型
|
||||
* @param cmpClazz 节点组件类
|
||||
*/
|
||||
public static void addNode(String nodeId, String name, NodeTypeEnum type, Class<?> cmpClazz) {
|
||||
addNode(nodeId, name, type, cmpClazz, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 node
|
||||
*
|
||||
* @param nodeId 节点id
|
||||
* @param name 节点名称
|
||||
* @param nodeType 节点类型
|
||||
* @param cmpClazzStr 节点组件类路径
|
||||
*/
|
||||
public static void addNode(String nodeId, String name, NodeTypeEnum nodeType, String cmpClazzStr) {
|
||||
Class<?> cmpClazz;
|
||||
try{
|
||||
try {
|
||||
cmpClazz = Class.forName(cmpClazzStr);
|
||||
}catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
throw new ComponentCannotRegisterException(e.getMessage());
|
||||
}
|
||||
addNode(nodeId, name, NodeTypeEnum.COMMON, cmpClazz, null);
|
||||
addNode(nodeId, name, nodeType, cmpClazz, null);
|
||||
}
|
||||
|
||||
public static void addCommonNode(String nodeId, String name, Class<?> cmpClazz){
|
||||
addNode(nodeId, name, NodeTypeEnum.COMMON, cmpClazz, null);
|
||||
}
|
||||
|
||||
public static void addSwitchNode(String nodeId, String name, String cmpClazzStr){
|
||||
Class<?> cmpClazz;
|
||||
try{
|
||||
cmpClazz = Class.forName(cmpClazzStr);
|
||||
}catch (Exception e){
|
||||
throw new ComponentCannotRegisterException(e.getMessage());
|
||||
}
|
||||
addNode(nodeId, name, NodeTypeEnum.SWITCH, cmpClazz, null);
|
||||
}
|
||||
|
||||
public static void addSwitchNode(String nodeId, String name, Class<?> cmpClazz){
|
||||
addNode(nodeId, name, NodeTypeEnum.SWITCH, cmpClazz, null);
|
||||
}
|
||||
|
||||
public static void addIfNode(String nodeId, String name, String cmpClazzStr){
|
||||
Class<?> cmpClazz;
|
||||
try{
|
||||
cmpClazz = Class.forName(cmpClazzStr);
|
||||
}catch (Exception e){
|
||||
throw new ComponentCannotRegisterException(e.getMessage());
|
||||
}
|
||||
addNode(nodeId, name, NodeTypeEnum.IF, cmpClazz, null);
|
||||
}
|
||||
|
||||
public static void addIfNode(String nodeId, String name, Class<?> cmpClazz){
|
||||
addNode(nodeId, name, NodeTypeEnum.IF, cmpClazz, null);
|
||||
}
|
||||
|
||||
public static void addForNode(String nodeId, String name, String cmpClazzStr){
|
||||
Class<?> cmpClazz;
|
||||
try{
|
||||
cmpClazz = Class.forName(cmpClazzStr);
|
||||
}catch (Exception e){
|
||||
throw new ComponentCannotRegisterException(e.getMessage());
|
||||
}
|
||||
addNode(nodeId, name, NodeTypeEnum.FOR, cmpClazz, null);
|
||||
}
|
||||
|
||||
public static void addForNode(String nodeId, String name, Class<?> cmpClazz){
|
||||
addNode(nodeId, name, NodeTypeEnum.FOR, cmpClazz, null);
|
||||
}
|
||||
|
||||
public static void addWhileNode(String nodeId, String name, String cmpClazzStr){
|
||||
Class<?> cmpClazz;
|
||||
try{
|
||||
cmpClazz = Class.forName(cmpClazzStr);
|
||||
}catch (Exception e){
|
||||
throw new ComponentCannotRegisterException(e.getMessage());
|
||||
}
|
||||
addNode(nodeId, name, NodeTypeEnum.WHILE, cmpClazz, null);
|
||||
}
|
||||
|
||||
public static void addWhileNode(String nodeId, String name, Class<?> cmpClazz){
|
||||
addNode(nodeId, name, NodeTypeEnum.WHILE, cmpClazz, null);
|
||||
}
|
||||
|
||||
public static void addBreakNode(String nodeId, String name, String cmpClazzStr){
|
||||
Class<?> cmpClazz;
|
||||
try{
|
||||
cmpClazz = Class.forName(cmpClazzStr);
|
||||
}catch (Exception e){
|
||||
throw new ComponentCannotRegisterException(e.getMessage());
|
||||
}
|
||||
addNode(nodeId, name, NodeTypeEnum.BREAK, cmpClazz, null);
|
||||
}
|
||||
|
||||
public static void addBreakNode(String nodeId, String name, Class<?> cmpClazz){
|
||||
addNode(nodeId, name, NodeTypeEnum.BREAK, cmpClazz, null);
|
||||
}
|
||||
|
||||
public static void addCommonScriptNode(String nodeId, String name, String script){
|
||||
addNode(nodeId, name, NodeTypeEnum.SCRIPT, ScriptCommonComponent.class, script);
|
||||
}
|
||||
|
||||
public static void addSwitchScriptNode(String nodeId, String name, String script){
|
||||
addNode(nodeId, name, NodeTypeEnum.SWITCH_SCRIPT, ScriptSwitchComponent.class, script);
|
||||
}
|
||||
|
||||
public static void addIfScriptNode(String nodeId, String name, String script){
|
||||
addNode(nodeId, name, NodeTypeEnum.IF_SCRIPT, ScriptIfComponent.class, script);
|
||||
}
|
||||
|
||||
public static void addForScriptNode(String nodeId, String name, String script){
|
||||
addNode(nodeId, name, NodeTypeEnum.FOR_SCRIPT, ScriptForComponent.class, script);
|
||||
}
|
||||
|
||||
public static void addWhileScriptNode(String nodeId, String name, String script){
|
||||
addNode(nodeId, name, NodeTypeEnum.WHILE_SCRIPT, ScriptWhileComponent.class, script);
|
||||
}
|
||||
|
||||
public static void addBreakScriptNode(String nodeId, String name, String script){
|
||||
addNode(nodeId, name, NodeTypeEnum.BREAK_SCRIPT, ScriptBreakComponent.class, script);
|
||||
/**
|
||||
* 添加脚本 node
|
||||
*
|
||||
* @param nodeId 节点id
|
||||
* @param name 节点名称
|
||||
* @param nodeType 节点类型
|
||||
* @param script 脚本
|
||||
*/
|
||||
public static void addScriptNode(String nodeId, String name, NodeTypeEnum nodeType, String script) {
|
||||
addNode(nodeId, name, nodeType, ScriptComponent.ScriptComponentClassMap.get(nodeType), script);
|
||||
}
|
||||
|
||||
private static void addNode(String nodeId, String name, NodeTypeEnum type, Class<?> cmpClazz, String script) {
|
||||
@@ -208,7 +144,7 @@ public class FlowBus {
|
||||
//判断此类是否是声明式的组件,如果是声明式的组件,就用动态代理生成实例
|
||||
//如果不是声明式的,就用传统的方式进行判断
|
||||
List<NodeComponent> cmpInstances = new ArrayList<>();
|
||||
if (LiteFlowProxyUtil.isDeclareCmp(cmpClazz)){
|
||||
if (LiteFlowProxyUtil.isDeclareCmp(cmpClazz)) {
|
||||
//这里的逻辑要仔细看下
|
||||
//如果是spring体系,把原始的类往spring上下文中进行注册,那么会走到ComponentScanner中
|
||||
//由于ComponentScanner中已经对原始类进行了动态代理,出来的对象已经变成了动态代理类,所以这时候的bean已经是NodeComponent的子类了
|
||||
@@ -217,16 +153,16 @@ public class FlowBus {
|
||||
//这里用ContextAware的spi机制来判断是否spring体系
|
||||
ContextAware contextAware = ContextAwareHolder.loadContextAware();
|
||||
Object bean = ContextAwareHolder.loadContextAware().registerBean(nodeId, cmpClazz);
|
||||
if (LocalContextAware.class.isAssignableFrom(contextAware.getClass())){
|
||||
if (LocalContextAware.class.isAssignableFrom(contextAware.getClass())) {
|
||||
cmpInstances = LiteFlowProxyUtil.proxy2NodeComponent(bean, nodeId);
|
||||
}else {
|
||||
} else {
|
||||
cmpInstances = ListUtil.toList((NodeComponent) bean);
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
//以node方式配置,本质上是为了适配无spring的环境,如果有spring环境,其实不用这么配置
|
||||
//这里的逻辑是判断是否能从spring上下文中取到,如果没有spring,则就是new instance了
|
||||
//如果是script类型的节点,因为class只有一个,所以也不能注册进spring上下文,注册的时候需要new Instance
|
||||
if (!type.isScript()){
|
||||
if (!type.isScript()) {
|
||||
cmpInstances = ListUtil.toList((NodeComponent) ContextAwareHolder.loadContextAware().registerOrGet(nodeId, cmpClazz));
|
||||
}
|
||||
// 去除null元素
|
||||
@@ -254,11 +190,11 @@ public class FlowBus {
|
||||
Node node = nodes.get(i);
|
||||
NodeComponent cmpInstance = cmpInstances.get(i);
|
||||
//如果是脚本节点,则还要加载script脚本
|
||||
if (type.isScript()){
|
||||
if (StrUtil.isNotBlank(script)){
|
||||
if (type.isScript()) {
|
||||
if (StrUtil.isNotBlank(script)) {
|
||||
node.setScript(script);
|
||||
((ScriptComponent)cmpInstance).loadScript(script);
|
||||
}else{
|
||||
((ScriptComponent) cmpInstance).loadScript(script);
|
||||
} else {
|
||||
String errorMsg = StrUtil.format("script for node[{}] is empty", nodeId);
|
||||
throw new ScriptLoadException(errorMsg);
|
||||
}
|
||||
@@ -269,7 +205,7 @@ public class FlowBus {
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
String error = StrUtil.format("component[{}] register error", StrUtil.isEmpty(name)?nodeId:StrUtil.format("{}({})",nodeId,name));
|
||||
String error = StrUtil.format("component[{}] register error", StrUtil.isEmpty(name) ? nodeId : StrUtil.format("{}({})", nodeId, name));
|
||||
LOG.error(e.getMessage());
|
||||
throw new ComponentCannotRegisterException(error);
|
||||
}
|
||||
@@ -283,19 +219,19 @@ public class FlowBus {
|
||||
//那condNodeMap共用有关系么,原则上没有关系。但是从设计理念上,以后应该要分开
|
||||
//tag和condNodeMap这2个属性不属于全局概念,属于每个chain范围的属性
|
||||
public static Node copyNode(String nodeId) {
|
||||
try{
|
||||
try {
|
||||
Node node = nodeMap.get(nodeId);
|
||||
return node.copy();
|
||||
}catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, Node> getNodeMap(){
|
||||
public static Map<String, Node> getNodeMap() {
|
||||
return nodeMap;
|
||||
}
|
||||
|
||||
public static Map<String, Chain> getChainMap(){
|
||||
public static Map<String, Chain> getChainMap() {
|
||||
return chainMap;
|
||||
}
|
||||
|
||||
@@ -307,12 +243,13 @@ public class FlowBus {
|
||||
|
||||
public static void cleanScriptCache() {
|
||||
//如果引入了脚本组件SPI,则还需要清理脚本的缓存
|
||||
try{
|
||||
try {
|
||||
ScriptExecutor scriptExecutor = ScriptExecutorFactory.loadInstance().getScriptExecutor();
|
||||
if (ObjectUtil.isNotNull(scriptExecutor)){
|
||||
if (ObjectUtil.isNotNull(scriptExecutor)) {
|
||||
scriptExecutor.cleanCache();
|
||||
}
|
||||
}catch (ScriptSpiException ignored){}
|
||||
} catch (ScriptSpiException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void refreshFlowMetaData(FlowParserTypeEnum type, String content) throws Exception {
|
||||
@@ -325,18 +262,18 @@ public class FlowBus {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean removeChain(String chainId){
|
||||
if (containChain(chainId)){
|
||||
public static boolean removeChain(String chainId) {
|
||||
if (containChain(chainId)) {
|
||||
chainMap.remove(chainId);
|
||||
return true;
|
||||
}else{
|
||||
} else {
|
||||
String errMsg = StrUtil.format("cannot find the chain[{}]", chainId);
|
||||
LOG.error(errMsg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeChain(String... chainIds){
|
||||
public static void removeChain(String... chainIds) {
|
||||
Arrays.stream(chainIds).forEach(FlowBus::removeChain);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.flowmeta;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.core.FlowExecutorHolder;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.flow.FlowBus;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.property.LiteflowConfig;
|
||||
@@ -26,7 +27,7 @@ public class FlowMetaTest extends BaseTest {
|
||||
//测试动态添加元信息节点
|
||||
@Test
|
||||
public void testFlowMeta() {
|
||||
FlowBus.addCommonNode("d", "d组件", DCmp.class);
|
||||
FlowBus.addNode("d", "d组件", NodeTypeEnum.COMMON, DCmp.class);
|
||||
LiteflowResponse response= flowExecutor.execute2Resp("chain1", "it's a request");
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
Assert.assertEquals("a==>b==>c==>d[d组件]", response.getExecuteStepStr());
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.yomahub.liteflow.test.flowmeta;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.flow.FlowBus;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
@@ -24,7 +25,7 @@ public class FlowMetaELSpringTest extends BaseTest {
|
||||
//测试动态添加元信息节点
|
||||
@Test
|
||||
public void testFlowMeta() {
|
||||
FlowBus.addCommonNode("d", "d组件", DCmp.class);
|
||||
FlowBus.addNode("d", "d组件", NodeTypeEnum.COMMON, DCmp.class);
|
||||
LiteflowResponse response= flowExecutor.execute2Resp("chain1", "it's a request");
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
Assert.assertEquals("a==>b==>c==>d[d组件]", response.getExecuteStepStr());
|
||||
|
||||
Reference in New Issue
Block a user