mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-06-10 03:07:32 +08:00
feature #I44FT8 支持脚本语言的组件,并支持动态刷新脚本(版本特性)
This commit is contained in:
@@ -50,22 +50,33 @@ public abstract class JsonFlowParser extends FlowParser {
|
||||
//json格式,解析过程
|
||||
public void parseJsonObject(List<JSONObject> flowJsonObjectList) throws Exception {
|
||||
try {
|
||||
for (Map.Entry<String, NodeComponent> componentEntry : ComponentScanner.nodeComponentMap.entrySet()) {
|
||||
if (!FlowBus.containNode(componentEntry.getKey())) {
|
||||
FlowBus.addNode(componentEntry.getKey(), new Node(componentEntry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
for (JSONObject flowJsonObject : flowJsonObjectList) {
|
||||
//判断是以spring方式注册节点,还是以json方式注册
|
||||
if (ComponentScanner.nodeComponentMap.isEmpty()) {
|
||||
// 当存在<nodes>节点定义时,解析node节点
|
||||
if (flowJsonObject.getJSONObject("flow").containsKey("nodes")){
|
||||
JSONArray nodeArrayList = flowJsonObject.getJSONObject("flow").getJSONObject("nodes").getJSONArray("node");
|
||||
String id, name, clazz;
|
||||
String id, name, clazz, script;
|
||||
for (int i = 0; i < nodeArrayList.size(); i++) {
|
||||
JSONObject nodeObject = nodeArrayList.getJSONObject(i);
|
||||
id = nodeObject.getString("id");
|
||||
name = nodeObject.getString("name");
|
||||
clazz = nodeObject.getString("class");
|
||||
FlowBus.addNode(id, name, clazz);
|
||||
}
|
||||
} else {
|
||||
for (Map.Entry<String, NodeComponent> componentEntry : ComponentScanner.nodeComponentMap.entrySet()) {
|
||||
if (!FlowBus.containNode(componentEntry.getKey())) {
|
||||
FlowBus.addNode(componentEntry.getKey(), new Node(componentEntry.getValue()));
|
||||
|
||||
//如果有class的定义,则表明是java组件,无class的定义,则表明是脚本组件
|
||||
if (StrUtil.isNotBlank(clazz)){
|
||||
if (!FlowBus.containNode(id)){
|
||||
FlowBus.addNode(id, name, clazz);
|
||||
}
|
||||
}else{
|
||||
if (!FlowBus.containNode(id)){
|
||||
script = nodeObject.getString("script");
|
||||
FlowBus.addScriptNode(id, name, script);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ public abstract class XmlFlowParser extends FlowParser {
|
||||
name = e.attributeValue("name");
|
||||
clazz = e.attributeValue("class");
|
||||
|
||||
//如果有class的定义,则表明是java组件,无class的定义,则表明是脚本组件
|
||||
if (StrUtil.isNotBlank(clazz)){
|
||||
if (!FlowBus.containNode(id)){
|
||||
FlowBus.addNode(id, name, clazz);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.yomahub.liteflow.script;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.yomahub.liteflow.script.exception.ScriptSpiException;
|
||||
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
@@ -8,7 +9,7 @@ public class ScriptFactory {
|
||||
|
||||
private static ScriptFactory scriptFactory;
|
||||
|
||||
private static ScriptExecutor scriptExecutor;
|
||||
private ScriptExecutor scriptExecutor;
|
||||
|
||||
public static ScriptFactory loadInstance(){
|
||||
if (ObjectUtil.isNull(scriptFactory)){
|
||||
@@ -20,9 +21,12 @@ public class ScriptFactory {
|
||||
public ScriptExecutor getScriptExecutor(){
|
||||
if (ObjectUtil.isNull(scriptExecutor)){
|
||||
ServiceLoader<ScriptExecutor> loader = ServiceLoader.load(ScriptExecutor.class);
|
||||
|
||||
if (loader.iterator().hasNext()){
|
||||
scriptExecutor = loader.iterator().next().init();
|
||||
return scriptExecutor;
|
||||
}else{
|
||||
throw new ScriptSpiException("script spi component failed to load");
|
||||
}
|
||||
}
|
||||
return scriptExecutor;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
package com.yomahub.liteflow.script.exception;
|
||||
|
||||
/**
|
||||
* 脚本SPI插件加载异常
|
||||
* @author Bryan.Zhang
|
||||
* @since 2.5.11
|
||||
*/
|
||||
public class ScriptSpiException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 异常信息 */
|
||||
private String message;
|
||||
|
||||
public ScriptSpiException(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-script-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# QLExpress的实现
|
||||
com.yomahub.liteflow.script.qlexpress.QLExpressScriptExecutor
|
||||
@@ -52,6 +52,12 @@
|
||||
<artifactId>zkclient</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-script-qlexpress</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.yomahub.liteflow.springboot.config.LiteflowPropertyAutoConfiguration,\
|
||||
com.yomahub.liteflow.springboot.config.LiteflowExecutorAutoConfiguration,\
|
||||
com.yomahub.liteflow.springboot.config.LiteflowMainAutoConfiguration
|
||||
|
||||
|
||||
com.yomahub.liteflow.springboot.config.LiteflowMainAutoConfiguration
|
||||
@@ -3,8 +3,11 @@ package com.yomahub.liteflow.test.aop;
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.entity.data.DefaultSlot;
|
||||
import com.yomahub.liteflow.entity.data.LiteflowResponse;
|
||||
import com.yomahub.liteflow.flow.FlowBus;
|
||||
import com.yomahub.liteflow.spring.ComponentScanner;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import com.yomahub.liteflow.test.aop.aspect.CmpAspect;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -55,4 +58,10 @@ public class LFGlobalAOPTest extends BaseTest {
|
||||
Assert.assertEquals("before_after", response.getSlot().getData("d"));
|
||||
Assert.assertEquals("before_after", response.getSlot().getData("e"));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanScanCache(){
|
||||
BaseTest.cleanScanCache();
|
||||
ComponentScanner.cmpAroundAspect = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.yomahub.liteflow.test.scriptnode;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.entity.data.DefaultSlot;
|
||||
import com.yomahub.liteflow.entity.data.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下的脚本组件
|
||||
* @author Bryan.Zhang
|
||||
* @since 2.5.11
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@TestPropertySource(value = "classpath:/scriptnode/application.properties")
|
||||
@SpringBootTest(classes = LiteflowScriptSpringbootTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"com.yomahub.liteflow.test.scriptnode.cmp"})
|
||||
public class LiteflowScriptSpringbootTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Test
|
||||
public void testScript1() {
|
||||
LiteflowResponse<DefaultSlot> response = flowExecutor.execute2Resp("chain1", "arg");
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
Assert.assertEquals(Integer.valueOf(6), response.getSlot().getData("s1"));
|
||||
}
|
||||
}
|
||||
@@ -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.scriptnode.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("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.scriptnode.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("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.scriptnode.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("c")
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
liteflow.rule-source=scriptnode/flow.xml
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<nodes>
|
||||
<node id="s1">
|
||||
<![CDATA[
|
||||
a=3;
|
||||
b=2;
|
||||
slot.setData("s1",a*b);
|
||||
]]>
|
||||
</node>
|
||||
</nodes>
|
||||
|
||||
<chain name="chain1">
|
||||
<then value="a,b,c,s1"/>
|
||||
</chain>
|
||||
</flow>
|
||||
Reference in New Issue
Block a user