Skip to content

Commit

Permalink
feature #I5IA5U 提供节点包装语法+替补节点的功能,增加el表达式来完成
Browse files Browse the repository at this point in the history
  • Loading branch information
bryan31 committed Jul 25, 2022
1 parent 2f51773 commit daa65d0
Show file tree
Hide file tree
Showing 14 changed files with 236 additions and 0 deletions.
Expand Up @@ -66,6 +66,7 @@ public LiteFlowChainELBuilder() {
expressRunner.addFunctionAndClassMethod("id", Object.class, new IdOperator());
expressRunner.addFunctionAndClassMethod("ignoreError", Object.class, new IgnoreErrorOperator());
expressRunner.addFunctionAndClassMethod("threadPool", Object.class, new ThreadPoolOperator());
expressRunner.addFunction("node", new NodeOperator());
}

//在parser中chain的build是2段式的,因为涉及到依赖问题,以前是递归parser
Expand Down
@@ -0,0 +1,65 @@
package com.yomahub.liteflow.builder.el.operator;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ql.util.express.Operator;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.flow.element.Node;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.function.Predicate;

/**
* EL规则中的node的操作符
* @author Bryan.Zhang
* @since 2.8.3
*/
public class NodeOperator extends Operator {

private final Logger LOG = LoggerFactory.getLogger(this.getClass());

@Override
public Object executeInner(Object[] objects) throws Exception {
if (ArrayUtil.isEmpty(objects)){
throw new Exception();
}

if (objects.length != 1){
LOG.error("parameter error");
throw new Exception();
}

String nodeId;
if (objects[0] instanceof String){
nodeId = (String) objects[0];
}else{
LOG.error("The value must be Node item!");
throw new Exception();
}

if (FlowBus.containNode(nodeId)){
return FlowBus.getNode(nodeId);
}else{
LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
if (StrUtil.isNotBlank(liteflowConfig.getSubstituteCmpClass())){
Node substituteNode = FlowBus.getNodeMap().values().stream().filter(node
-> node.getInstance().getClass().getName().equals(liteflowConfig.getSubstituteCmpClass())).findFirst().orElse(null);
if (ObjectUtil.isNotNull(substituteNode)){
return substituteNode;
}else{
String error = StrUtil.format("This node[{}] cannot be found", nodeId);
LOG.error(error);
throw new Exception();
}
}else{
String error = StrUtil.format("This node[{}] cannot be found, or you can configure an substitute node", nodeId);
LOG.error(error);
throw new Exception();
}
}
}
}
Expand Up @@ -87,6 +87,9 @@ public class LiteflowConfig {
//是否打印执行中的日志
private Boolean printExecutionLog;

//替补组件class路径
private String substituteCmpClass;

public Boolean getEnable() {
if (ObjectUtil.isNull(enable)) {
return Boolean.TRUE;
Expand Down Expand Up @@ -333,4 +336,12 @@ public Boolean getPrintExecutionLog() {
public void setPrintExecutionLog(Boolean printExecutionLog) {
this.printExecutionLog = printExecutionLog;
}

public String getSubstituteCmpClass() {
return substituteCmpClass;
}

public void setSubstituteCmpClass(String substituteCmpClass) {
this.substituteCmpClass = substituteCmpClass;
}
}
Expand Up @@ -62,6 +62,9 @@ public class LiteflowProperty {
//是否打印执行过程中的日志
private boolean printExecutionLog;

//替补组件的class路径
private String substituteCmpClass;

public boolean isEnable() {
return enable;
}
Expand Down Expand Up @@ -197,4 +200,12 @@ public String getRequestIdGeneratorClass() {
public void setRequestIdGeneratorClass(String requestIdGeneratorClass) {
this.requestIdGeneratorClass = requestIdGeneratorClass;
}

public String getSubstituteCmpClass() {
return substituteCmpClass;
}

public void setSubstituteCmpClass(String substituteCmpClass) {
this.substituteCmpClass = substituteCmpClass;
}
}
Expand Up @@ -45,6 +45,7 @@ public LiteflowConfig liteflowConfig(LiteflowProperty property, LiteflowMonitorP
liteflowConfig.setMainExecutorWorks(property.getMainExecutorWorks());
liteflowConfig.setMainExecutorClass(property.getMainExecutorClass());
liteflowConfig.setPrintExecutionLog(property.isPrintExecutionLog());
liteflowConfig.setSubstituteCmpClass(property.getSubstituteCmpClass());
return liteflowConfig;
}
}
Expand Up @@ -119,6 +119,13 @@
"sourceType": "com.yomahub.liteflow.springboot.LiteflowProperty",
"defaultValue": true
},
{
"name": "liteflow.substitute-cmp-class",
"type": "java.lang.String",
"description": "substitute component class.",
"sourceType": "com.yomahub.liteflow.springboot.LiteflowProperty",
"defaultValue": ""
},
{
"name": "liteflow.monitor.enable-log",
"type": "java.lang.Boolean",
Expand Down
Expand Up @@ -14,6 +14,7 @@ liteflow.retry-count=0
liteflow.support-multiple-type=false
liteflow.node-executor-class=com.yomahub.liteflow.flow.executor.DefaultNodeExecutor
liteflow.print-execution-log=true
liteflow.substitute-cmp-class=
liteflow.monitor.enable-log=false
liteflow.monitor.queue-limit=200
liteflow.monitor.delay=300000
Expand Down
@@ -0,0 +1,44 @@
package com.yomahub.liteflow.test.substituteNode;

import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
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.junit4.SpringRunner;

import javax.annotation.Resource;

/**
* springboot环境EL替补节点的测试
* @author Bryan.Zhang
*/
@RunWith(SpringRunner.class)
@TestPropertySource(value = "classpath:/substituteNode/application.properties")
@SpringBootTest(classes = SubstituteSpringbootTest.class)
@EnableAutoConfiguration
@ComponentScan({"com.yomahub.liteflow.test.substituteNode.cmp"})
public class SubstituteSpringbootTest extends BaseTest {

@Resource
private FlowExecutor flowExecutor;

//最简单的情况
@Test
public void testSub1() throws Exception{
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
Assert.assertTrue(response.isSuccess());
}

//有替补节点
@Test
public void testSub2() throws Exception{
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
Assert.assertTrue(response.isSuccess());
}
}
@@ -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.substituteNode.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.substituteNode.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,21 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.substituteNode.cmp;

import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;

@Component("c")
public class CCmp extends NodeComponent {

@Override
public void process() {
System.out.println("CCmp 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.substituteNode.cmp;

import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;

@Component("sub")
public class SubCmp extends NodeComponent {

@Override
public void process() {
System.out.println("SubCmp executed!");
}

}
@@ -0,0 +1,2 @@
liteflow.rule-source=substituteNode/flow.el.xml
liteflow.substitute-cmp-class=com.yomahub.liteflow.test.substituteNode.cmp.SubCmp
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<chain name="chain1">
THEN(node("a"), node("b"), node("c"));
</chain>

<chain name="chain2">
THEN(node("a"), node("b"), node("93-nodeTEST"));
</chain>
</flow>

0 comments on commit daa65d0

Please sign in to comment.