Browse Source

feature #I6NGM3 LiteFlow支持多种不同语言脚本混合调用的特性

everywhere.z 2 years ago
parent
commit
36526c1903
36 changed files with 410 additions and 59 deletions
  1. 6 1
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java
  2. 14 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/prop/NodePropBean.java
  3. 2 0
      liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java
  4. 3 3
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptBreakComponent.java
  5. 3 3
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptCommonComponent.java
  6. 1 1
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptComponent.java
  7. 3 3
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptForComponent.java
  8. 3 3
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptIfComponent.java
  9. 3 3
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptSwitchComponent.java
  10. 3 3
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptWhileComponent.java
  11. 44 0
      liteflow-core/src/main/java/com/yomahub/liteflow/enums/ScriptTypeEnum.java
  12. 8 10
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java
  13. 10 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java
  14. 0 1
      liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorFile.java
  15. 6 2
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/ParserHelper.java
  16. 4 0
      liteflow-core/src/main/java/com/yomahub/liteflow/script/ScriptExecutor.java
  17. 43 9
      liteflow-core/src/main/java/com/yomahub/liteflow/script/ScriptExecutorFactory.java
  18. 1 3
      liteflow-core/src/main/java/com/yomahub/liteflow/script/jsr223/JSR223ScriptExecutor.java
  19. 6 0
      liteflow-script-plugin/liteflow-script-graaljs/src/main/java/com/yomahub/liteflow/script/graaljs/GraalJavaScriptExecutor.java
  20. 3 2
      liteflow-script-plugin/liteflow-script-groovy/src/main/java/com/yomahub/liteflow/script/groovy/GroovyScriptExecutor.java
  21. 5 4
      liteflow-script-plugin/liteflow-script-javascript/src/main/java/com/yomahub/liteflow/script/javascript/JavaScriptExecutor.java
  22. 3 2
      liteflow-script-plugin/liteflow-script-lua/src/main/java/com/yomahub/liteflow/script/lua/LuaScriptExecutor.java
  23. 3 2
      liteflow-script-plugin/liteflow-script-python/src/main/java/com/yomahub/liteflow/script/python/PythonScriptExecutor.java
  24. 6 0
      liteflow-script-plugin/liteflow-script-qlexpress/src/main/java/com/yomahub/liteflow/script/qlexpress/QLExpressScriptExecutor.java
  25. 0 1
      liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/monitorFile/LiteflowMonitorFileTest.java
  26. 44 0
      liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/pom.xml
  27. 22 0
      liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java
  28. 51 0
      liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/java/com/yomahub/liteflow/test/script/multi/language/MultiLanguageELTest.java
  29. 20 0
      liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/java/com/yomahub/liteflow/test/script/multi/language/cmp/ACmp.java
  30. 21 0
      liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/java/com/yomahub/liteflow/test/script/multi/language/cmp/BCmp.java
  31. 21 0
      liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/java/com/yomahub/liteflow/test/script/multi/language/cmp/CCmp.java
  32. 1 0
      liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/resources/multiLanguage/application.properties
  33. 42 0
      liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/resources/multiLanguage/flow.xml
  34. 2 2
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/catchcase/CatchELSpringbootTest.java
  35. 2 1
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/monitorFile/application.properties
  36. 1 0
      liteflow-testcase-el/pom.xml

+ 6 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java

@@ -146,12 +146,17 @@ public class LiteFlowNodeBuilder {
         return this;
     }
 
+    public LiteFlowNodeBuilder setLanguage(String language) {
+        this.node.setLanguage(language);
+        return this;
+    }
+
     public void build() {
         checkBuild();
         try {
             // 用于处理脚本 node
            if (this.node.getType().isScript()){
-               FlowBus.addScriptNode(this.node.getId(), this.node.getName(), this.node.getType(), this.node.getScript());
+               FlowBus.addScriptNode(this.node.getId(), this.node.getName(), this.node.getType(), this.node.getScript(), this.node.getLanguage());
            }
            // 用于处理普通 node
            else{

+ 14 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/prop/NodePropBean.java

@@ -35,6 +35,11 @@ public class NodePropBean {
 	 */
 	String file;
 
+	/**
+	 * 脚本语言
+	 */
+	String language;
+
 	public String getId() {
 		return id;
 	}
@@ -88,4 +93,13 @@ public class NodePropBean {
 		this.file = file;
 		return this;
 	}
+
+	public String getLanguage() {
+		return language;
+	}
+
+	public NodePropBean setLanguage(String language) {
+		this.language = language;
+		return this;
+	}
 }

+ 2 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java

@@ -23,6 +23,8 @@ public interface ChainConstant {
 
     String NAME = "name";
 
+    String LANGUAGE = "language";
+
     String VALUE = "value";
 
     String ANY = "any";

+ 3 - 3
liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptBreakComponent.java

@@ -19,11 +19,11 @@ public class ScriptBreakComponent extends NodeBreakComponent implements ScriptCo
         wrap.setSlotIndex(this.getSlotIndex());
         wrap.setTag(this.getTag());
         wrap.setCmpData(this.getCmpData(Map.class));
-        return (boolean) ScriptExecutorFactory.loadInstance().getScriptExecutor().execute(wrap);
+        return (boolean) ScriptExecutorFactory.loadInstance().getScriptExecutor(this.getRefNode().getLanguage()).execute(wrap);
     }
 
     @Override
-    public void loadScript(String script) {
-        ScriptExecutorFactory.loadInstance().getScriptExecutor().load(getNodeId(), script);
+    public void loadScript(String script, String language) {
+        ScriptExecutorFactory.loadInstance().getScriptExecutor(language).load(getNodeId(), script);
     }
 }

+ 3 - 3
liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptCommonComponent.java

@@ -24,12 +24,12 @@ public class ScriptCommonComponent extends NodeComponent implements ScriptCompon
         wrap.setSlotIndex(this.getSlotIndex());
         wrap.setTag(this.getTag());
         wrap.setCmpData(this.getCmpData(Map.class));
-        ScriptExecutorFactory.loadInstance().getScriptExecutor().execute(wrap);
+        ScriptExecutorFactory.loadInstance().getScriptExecutor(this.getRefNode().getLanguage()).execute(wrap);
     }
 
     @Override
-    public void loadScript(String script) {
+    public void loadScript(String script, String language) {
         log.info("load script for component[{}]", getDisplayName());
-        ScriptExecutorFactory.loadInstance().getScriptExecutor().load(getNodeId(), script);
+        ScriptExecutorFactory.loadInstance().getScriptExecutor(language).load(getNodeId(), script);
     }
 }

+ 1 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptComponent.java

@@ -28,5 +28,5 @@ public interface ScriptComponent {
      * 加载脚本
      * @param script
      */
-    void loadScript(String script);
+    void loadScript(String script, String language);
 }

+ 3 - 3
liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptForComponent.java

@@ -19,11 +19,11 @@ public class ScriptForComponent extends NodeForComponent implements ScriptCompon
         wrap.setSlotIndex(this.getSlotIndex());
         wrap.setTag(this.getTag());
         wrap.setCmpData(this.getCmpData(Map.class));
-        return (int) ScriptExecutorFactory.loadInstance().getScriptExecutor().execute(wrap);
+        return (int) ScriptExecutorFactory.loadInstance().getScriptExecutor(this.getRefNode().getLanguage()).execute(wrap);
     }
 
     @Override
-    public void loadScript(String script) {
-        ScriptExecutorFactory.loadInstance().getScriptExecutor().load(getNodeId(), script);
+    public void loadScript(String script, String language) {
+        ScriptExecutorFactory.loadInstance().getScriptExecutor(language).load(getNodeId(), script);
     }
 }

+ 3 - 3
liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptIfComponent.java

@@ -19,11 +19,11 @@ public class ScriptIfComponent extends NodeIfComponent implements ScriptComponen
         wrap.setSlotIndex(this.getSlotIndex());
         wrap.setTag(this.getTag());
         wrap.setCmpData(this.getCmpData(Map.class));
-        return (boolean)ScriptExecutorFactory.loadInstance().getScriptExecutor().execute(wrap);
+        return (boolean)ScriptExecutorFactory.loadInstance().getScriptExecutor(this.getRefNode().getLanguage()).execute(wrap);
     }
 
     @Override
-    public void loadScript(String script) {
-        ScriptExecutorFactory.loadInstance().getScriptExecutor().load(getNodeId(), script);
+    public void loadScript(String script, String language) {
+        ScriptExecutorFactory.loadInstance().getScriptExecutor(language).load(getNodeId(), script);
     }
 }

+ 3 - 3
liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptSwitchComponent.java

@@ -20,11 +20,11 @@ public class ScriptSwitchComponent extends NodeSwitchComponent implements Script
         wrap.setSlotIndex(this.getSlotIndex());
         wrap.setTag(this.getTag());
         wrap.setCmpData(this.getCmpData(Map.class));
-        return (String)ScriptExecutorFactory.loadInstance().getScriptExecutor().execute(wrap);
+        return (String)ScriptExecutorFactory.loadInstance().getScriptExecutor(this.getRefNode().getLanguage()).execute(wrap);
     }
 
     @Override
-    public void loadScript(String script) {
-        ScriptExecutorFactory.loadInstance().getScriptExecutor().load(getNodeId(), script);
+    public void loadScript(String script, String language) {
+        ScriptExecutorFactory.loadInstance().getScriptExecutor(language).load(getNodeId(), script);
     }
 }

+ 3 - 3
liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptWhileComponent.java

@@ -20,11 +20,11 @@ public class ScriptWhileComponent extends NodeWhileComponent implements ScriptCo
         wrap.setSlotIndex(this.getSlotIndex());
         wrap.setTag(this.getTag());
         wrap.setCmpData(this.getCmpData(Map.class));
-        return (boolean) ScriptExecutorFactory.loadInstance().getScriptExecutor().execute(wrap);
+        return (boolean) ScriptExecutorFactory.loadInstance().getScriptExecutor(this.getRefNode().getLanguage()).execute(wrap);
     }
 
     @Override
-    public void loadScript(String script) {
-        ScriptExecutorFactory.loadInstance().getScriptExecutor().load(getNodeId(), script);
+    public void loadScript(String script, String language) {
+        ScriptExecutorFactory.loadInstance().getScriptExecutor(language).load(getNodeId(), script);
     }
 }

+ 44 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/enums/ScriptTypeEnum.java

@@ -0,0 +1,44 @@
+package com.yomahub.liteflow.enums;
+
+public enum ScriptTypeEnum {
+
+    GROOVY("groovy", "groovy"),
+    QLEXPRESS("qlexpress", "qlexpress"),
+    JS("javascript", "js"),
+    PYTHON("python", "python"),
+    LUA("luaj", "lua")
+    ;
+    private String engineName;
+
+    private String displayName;
+
+    ScriptTypeEnum(String engineName, String displayName) {
+        this.engineName = engineName;
+        this.displayName = displayName;
+    }
+
+    public String getEngineName() {
+        return engineName;
+    }
+
+    public void setEngineName(String engineName) {
+        this.engineName = engineName;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(String displayName) {
+        this.displayName = displayName;
+    }
+
+    public static ScriptTypeEnum getEnumByDisplayName(String displayName) {
+        for (ScriptTypeEnum e : ScriptTypeEnum.values()) {
+            if (e.getDisplayName().equals(displayName)) {
+                return e;
+            }
+        }
+        return null;
+    }
+}

+ 8 - 10
liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java

@@ -106,7 +106,7 @@ public class FlowBus {
      * @param cmpClazz 节点组件类
      */
     public static void addNode(String nodeId, String name, NodeTypeEnum type, Class<?> cmpClazz) {
-        addNode(nodeId, name, type, cmpClazz, null);
+        addNode(nodeId, name, type, cmpClazz, null, null);
     }
 
     /**
@@ -124,7 +124,7 @@ public class FlowBus {
         } catch (Exception e) {
             throw new ComponentCannotRegisterException(e.getMessage());
         }
-        addNode(nodeId, name, nodeType, cmpClazz, null);
+        addNode(nodeId, name, nodeType, cmpClazz, null, null);
     }
 
     /**
@@ -135,11 +135,11 @@ public class FlowBus {
      * @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);
+    public static void addScriptNode(String nodeId, String name, NodeTypeEnum nodeType, String script, String language) {
+        addNode(nodeId, name, nodeType, ScriptComponent.ScriptComponentClassMap.get(nodeType), script, language);
     }
 
-    private static void addNode(String nodeId, String name, NodeTypeEnum type, Class<?> cmpClazz, String script) {
+    private static void addNode(String nodeId, String name, NodeTypeEnum type, Class<?> cmpClazz, String script, String language) {
         try {
             //判断此类是否是声明式的组件,如果是声明式的组件,就用动态代理生成实例
             //如果不是声明式的,就用传统的方式进行判断
@@ -193,7 +193,8 @@ public class FlowBus {
                 if (type.isScript()) {
                     if (StrUtil.isNotBlank(script)) {
                         node.setScript(script);
-                        ((ScriptComponent) cmpInstance).loadScript(script);
+                        node.setLanguage(language);
+                        ((ScriptComponent) cmpInstance).loadScript(script, language);
                     } else {
                         String errorMsg = StrUtil.format("script for node[{}] is empty", nodeId);
                         throw new ScriptLoadException(errorMsg);
@@ -244,10 +245,7 @@ public class FlowBus {
     public static void cleanScriptCache() {
         //如果引入了脚本组件SPI,则还需要清理脚本的缓存
         try {
-            ScriptExecutor scriptExecutor = ScriptExecutorFactory.loadInstance().getScriptExecutor();
-            if (ObjectUtil.isNotNull(scriptExecutor)) {
-                scriptExecutor.cleanCache();
-            }
+            ScriptExecutorFactory.loadInstance().cleanScriptCache();
         } catch (ScriptSpiException ignored) {
         }
     }

+ 10 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java

@@ -46,6 +46,8 @@ public class Node implements Executable,Cloneable{
 
 	private String script;
 
+	private String language;
+
 	private NodeComponent instance;
 
 	private String tag;
@@ -255,4 +257,12 @@ public class Node implements Executable,Cloneable{
 	public void removeCurrLoopObject(){
 		this.currLoopObject.remove();
 	}
+
+	public String getLanguage() {
+		return language;
+	}
+
+	public void setLanguage(String language) {
+		this.language = language;
+	}
 }

+ 0 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorFile.java

@@ -51,7 +51,6 @@ public class MonitorFile {
      */
     public void create() {
         for (String filePath : CollUtil.distinct(PATH_LIST)) {
-            // 这里只监听两种类型,文件修改和文件覆盖
             WatchMonitor.createAll(filePath, new SimpleWatcher(){
                 @Override
                 public void onModify(WatchEvent<?> event, Path currentPath) {

+ 6 - 2
liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/ParserHelper.java

@@ -44,6 +44,7 @@ public class ParserHelper {
 		String script = nodePropBean.getScript();
 		String type = nodePropBean.getType();
 		String file = nodePropBean.getFile();
+		String language = nodePropBean.getLanguage();
 
 		//clazz有值的,基本都不是脚本节点
 		//脚本节点,都必须配置type
@@ -80,6 +81,7 @@ public class ParserHelper {
 				.setType(nodeTypeEnum)
 				.setScript(script)
 				.setFile(file)
+				.setLanguage(language)
 				.build();
 	}
 
@@ -98,7 +100,7 @@ public class ParserHelper {
 			// 当存在<nodes>节点定义时,解析node节点
 			if (ObjectUtil.isNotNull(nodesElement)) {
 				List<Element> nodeList = nodesElement.elements(NODE);
-				String id, name, clazz, type, script, file;
+				String id, name, clazz, type, script, file, language;
 				for (Element e : nodeList) {
 					id = e.attributeValue(ID);
 					name = e.attributeValue(NAME);
@@ -106,6 +108,7 @@ public class ParserHelper {
 					type = e.attributeValue(TYPE);
 					script = e.getText();
 					file = e.attributeValue(FILE);
+					language = e.attributeValue(LANGUAGE);
 
 					// 构建 node
 					NodePropBean nodePropBean = new NodePropBean()
@@ -114,7 +117,8 @@ public class ParserHelper {
 							.setClazz(clazz)
 							.setScript(script)
 							.setType(type)
-							.setFile(file);
+							.setFile(file)
+							.setLanguage(language);
 
 					ParserHelper.buildNode(nodePropBean);
 				}

+ 4 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/script/ScriptExecutor.java

@@ -1,5 +1,7 @@
 package com.yomahub.liteflow.script;
 
+import com.yomahub.liteflow.enums.ScriptTypeEnum;
+
 /**
  * 脚本执行器接口
  * @author Bryan.Zhang
@@ -14,4 +16,6 @@ public interface ScriptExecutor {
     Object execute(ScriptExecuteWrap wrap) throws Exception;
 
     void cleanCache();
+
+    ScriptTypeEnum scriptType();
 }

+ 43 - 9
liteflow-core/src/main/java/com/yomahub/liteflow/script/ScriptExecutorFactory.java

@@ -1,9 +1,15 @@
 package com.yomahub.liteflow.script;
 
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.enums.ScriptTypeEnum;
 import com.yomahub.liteflow.script.exception.ScriptSpiException;
 
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
 import java.util.ServiceLoader;
+import java.util.function.Consumer;
 
 /**
  * 脚本执行器工厂类
@@ -14,7 +20,9 @@ public class ScriptExecutorFactory {
 
     private static ScriptExecutorFactory scriptExecutorFactory;
 
-    private ScriptExecutor scriptExecutor;
+    private final Map<String,ScriptExecutor> scriptExecutorMap = new HashMap<>();
+
+    private final String NONE_LANGUAGE = "none";
 
     public static ScriptExecutorFactory loadInstance(){
         if (ObjectUtil.isNull(scriptExecutorFactory)){
@@ -23,17 +31,43 @@ public class ScriptExecutorFactory {
         return scriptExecutorFactory;
     }
 
-    public ScriptExecutor getScriptExecutor(){
-        if (ObjectUtil.isNull(scriptExecutor)){
+    public ScriptExecutor getScriptExecutor(String language){
+        if (StrUtil.isBlank(language)){
+            language = NONE_LANGUAGE;
+        }
+
+
+        if (!scriptExecutorMap.containsKey(language)){
             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");
+            ScriptExecutor scriptExecutor;
+            Iterator<ScriptExecutor> it = loader.iterator();
+            while(it.hasNext()){
+                scriptExecutor = it.next().init();
+                if (language.equals(NONE_LANGUAGE)){
+                    scriptExecutorMap.put(language, scriptExecutor);
+                    break;
+                }else{
+                    ScriptTypeEnum scriptType = ScriptTypeEnum.getEnumByDisplayName(language);
+                    if (ObjectUtil.isNull(scriptType)){
+                        throw new ScriptSpiException("script language config error");
+                    }
+                    if (scriptType.equals(scriptExecutor.scriptType())){
+                        scriptExecutorMap.put(language, scriptExecutor);
+                        break;
+                    }
+                }
             }
         }
-        return scriptExecutor;
+
+        if (scriptExecutorMap.containsKey(language)){
+            return scriptExecutorMap.get(language);
+        }else{
+            throw new ScriptSpiException("script spi component failed to load");
+        }
+    }
+
+    public void cleanScriptCache(){
+        this.scriptExecutorMap.forEach((key, value) -> value.cleanCache());
     }
 }

+ 1 - 3
liteflow-core/src/main/java/com/yomahub/liteflow/script/jsr223/JSR223ScriptExecutor.java

@@ -36,12 +36,10 @@ public abstract class JSR223ScriptExecutor implements ScriptExecutor {
     @Override
     public ScriptExecutor init() {
         ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
-        scriptEngine = scriptEngineManager.getEngineByName(scriptEngineName());
+        scriptEngine = scriptEngineManager.getEngineByName(this.scriptType().getEngineName());
         return this;
     }
 
-    protected abstract String scriptEngineName();
-
     protected String convertScript(String script){
         return script;
     }

+ 6 - 0
liteflow-script-plugin/liteflow-script-graaljs/src/main/java/com/yomahub/liteflow/script/graaljs/GraalJavaScriptExecutor.java

@@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.annotation.util.AnnoUtil;
 import com.yomahub.liteflow.context.ContextBean;
+import com.yomahub.liteflow.enums.ScriptTypeEnum;
 import com.yomahub.liteflow.script.ScriptBeanManager;
 import com.yomahub.liteflow.script.ScriptExecuteWrap;
 import com.yomahub.liteflow.script.ScriptExecutor;
@@ -111,4 +112,9 @@ public class GraalJavaScriptExecutor implements ScriptExecutor {
     public void cleanCache() {
         scriptMap.clear();
     }
+
+    @Override
+    public ScriptTypeEnum scriptType() {
+        return ScriptTypeEnum.JS;
+    }
 }

+ 3 - 2
liteflow-script-plugin/liteflow-script-groovy/src/main/java/com/yomahub/liteflow/script/groovy/GroovyScriptExecutor.java

@@ -1,5 +1,6 @@
 package com.yomahub.liteflow.script.groovy;
 
+import com.yomahub.liteflow.enums.ScriptTypeEnum;
 import com.yomahub.liteflow.script.jsr223.JSR223ScriptExecutor;
 
 /**
@@ -10,7 +11,7 @@ import com.yomahub.liteflow.script.jsr223.JSR223ScriptExecutor;
 public class GroovyScriptExecutor extends JSR223ScriptExecutor {
 
     @Override
-    protected String scriptEngineName() {
-        return "groovy";
+    public ScriptTypeEnum scriptType() {
+        return ScriptTypeEnum.GROOVY;
     }
 }

+ 5 - 4
liteflow-script-plugin/liteflow-script-javascript/src/main/java/com/yomahub/liteflow/script/javascript/JavaScriptExecutor.java

@@ -1,6 +1,7 @@
 package com.yomahub.liteflow.script.javascript;
 
 import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.enums.ScriptTypeEnum;
 import com.yomahub.liteflow.script.jsr223.JSR223ScriptExecutor;
 /**
  * JavaScript脚本语言的执行器实现
@@ -10,12 +11,12 @@ import com.yomahub.liteflow.script.jsr223.JSR223ScriptExecutor;
 public class JavaScriptExecutor extends JSR223ScriptExecutor {
 
     @Override
-    protected String scriptEngineName() {
-        return "javascript";
+    protected String convertScript(String script) {
+        return StrUtil.format("function process(){{}} process();",script);
     }
 
     @Override
-    protected String convertScript(String script) {
-        return StrUtil.format("function process(){{}} process();",script);
+    public ScriptTypeEnum scriptType() {
+        return ScriptTypeEnum.JS;
     }
 }

+ 3 - 2
liteflow-script-plugin/liteflow-script-lua/src/main/java/com/yomahub/liteflow/script/lua/LuaScriptExecutor.java

@@ -2,6 +2,7 @@ package com.yomahub.liteflow.script.lua;
 
 import cn.hutool.core.util.ReUtil;
 import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.enums.ScriptTypeEnum;
 import com.yomahub.liteflow.script.jsr223.JSR223ScriptExecutor;
 
 import java.util.Arrays;
@@ -15,8 +16,8 @@ import java.util.stream.Collectors;
  */
 public class LuaScriptExecutor extends JSR223ScriptExecutor {
     @Override
-    protected String scriptEngineName() {
-        return "luaj";
+    public ScriptTypeEnum scriptType() {
+        return ScriptTypeEnum.LUA;
     }
 
     @Override

+ 3 - 2
liteflow-script-plugin/liteflow-script-python/src/main/java/com/yomahub/liteflow/script/python/PythonScriptExecutor.java

@@ -2,6 +2,7 @@ package com.yomahub.liteflow.script.python;
 
 import cn.hutool.core.util.ReUtil;
 import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.enums.ScriptTypeEnum;
 import com.yomahub.liteflow.script.jsr223.JSR223ScriptExecutor;
 import java.util.Arrays;
 import java.util.List;
@@ -15,8 +16,8 @@ import java.util.stream.Collectors;
 public class PythonScriptExecutor extends JSR223ScriptExecutor {
 
     @Override
-    protected String scriptEngineName() {
-        return "python";
+    public ScriptTypeEnum scriptType() {
+        return ScriptTypeEnum.PYTHON;
     }
 
     @Override

+ 6 - 0
liteflow-script-plugin/liteflow-script-qlexpress/src/main/java/com/yomahub/liteflow/script/qlexpress/QLExpressScriptExecutor.java

@@ -10,6 +10,7 @@ import com.ql.util.express.ExpressRunner;
 import com.ql.util.express.InstructionSet;
 import com.yomahub.liteflow.annotation.util.AnnoUtil;
 import com.yomahub.liteflow.context.ContextBean;
+import com.yomahub.liteflow.enums.ScriptTypeEnum;
 import com.yomahub.liteflow.script.ScriptBeanManager;
 import com.yomahub.liteflow.script.ScriptExecuteWrap;
 import com.yomahub.liteflow.slot.DataBus;
@@ -116,4 +117,9 @@ public class QLExpressScriptExecutor implements ScriptExecutor {
         expressRunner.clearExpressCache();
         ReflectUtil.setFieldValue(expressRunner,"loader",new ExpressLoader(expressRunner));
     }
+
+    @Override
+    public ScriptTypeEnum scriptType() {
+        return ScriptTypeEnum.QLEXPRESS;
+    }
 }

+ 0 - 1
liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/monitorFile/LiteflowMonitorFileTest.java

@@ -32,7 +32,6 @@ public class LiteflowMonitorFileTest extends BaseTest {
         String content = FileUtil.readUtf8String(absolutePath);
         String newContent = content.replace("THEN(a, b, c);", "THEN(a, c, b);");
         FileUtil.writeString(newContent, new File(absolutePath), CharsetUtil.CHARSET_UTF_8);
-        Thread.sleep(1000L);
         LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
         Assert.assertEquals("a==>c==>b", response.getExecuteStepStr());
     }

+ 44 - 0
liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/pom.xml

@@ -0,0 +1,44 @@
+<?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>
+        <groupId>com.yomahub</groupId>
+        <artifactId>liteflow-testcase-el</artifactId>
+        <version>${revision}</version>
+    </parent>
+
+    <artifactId>liteflow-testcase-el-script-multi-language-springboot</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.yomahub</groupId>
+            <artifactId>liteflow-spring-boot-starter</artifactId>
+            <version>${revision}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.yomahub</groupId>
+            <artifactId>liteflow-script-groovy</artifactId>
+            <version>${revision}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.yomahub</groupId>
+            <artifactId>liteflow-script-javascript</artifactId>
+            <version>${revision}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.yomahub</groupId>
+            <artifactId>liteflow-script-python</artifactId>
+            <version>${revision}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 22 - 0
liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java

@@ -0,0 +1,22 @@
+package com.yomahub.liteflow.test;
+
+import com.yomahub.liteflow.core.FlowInitHook;
+import com.yomahub.liteflow.flow.FlowBus;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
+import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner;
+import com.yomahub.liteflow.spring.ComponentScanner;
+import com.yomahub.liteflow.thread.ExecutorHelper;
+import org.junit.AfterClass;
+
+public class BaseTest {
+
+    @AfterClass
+    public static void cleanScanCache(){
+        ComponentScanner.cleanCache();
+        FlowBus.cleanCache();
+        ExecutorHelper.loadInstance().clearExecutorServiceMap();
+        SpiFactoryCleaner.clean();
+        LiteflowConfigGetter.clean();
+        FlowInitHook.cleanHook();
+    }
+}

+ 51 - 0
liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/java/com/yomahub/liteflow/test/script/multi/language/MultiLanguageELTest.java

@@ -0,0 +1,51 @@
+package com.yomahub.liteflow.test.script.multi.language;
+
+import cn.hutool.core.io.resource.ResourceUtil;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.enums.FlowParserTypeEnum;
+import com.yomahub.liteflow.flow.FlowBus;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import com.yomahub.liteflow.util.JsonUtil;
+import groovy.lang.MetaClass;
+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;
+import java.util.Map;
+
+
+/**
+ * 测试springboot下的groovy脚本组件,基于xml配置
+ * @author Bryan.Zhang
+ * @since 2.6.0
+ */
+@RunWith(SpringRunner.class)
+@TestPropertySource(value = "classpath:/multiLanguage/application.properties")
+@SpringBootTest(classes = MultiLanguageELTest.class)
+@EnableAutoConfiguration
+@ComponentScan({"com.yomahub.liteflow.test.script.multi.language.cmp"})
+public class MultiLanguageELTest extends BaseTest {
+
+    @Resource
+    private FlowExecutor flowExecutor;
+
+    //测试普通脚本节点
+    @Test
+    public void testMultiLanguage1() {
+        LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+        DefaultContext context = response.getFirstContextBean();
+        Object student = context.getData("student");
+        Map<String,Object> studentMap = JsonUtil.parseObject(JsonUtil.toJsonString(student), Map.class);
+        Assert.assertTrue(response.isSuccess());
+        Assert.assertEquals(Integer.valueOf(18), context.getData("s1"));
+        Assert.assertEquals(10032, studentMap.get("studentID"));
+    }
+}

+ 20 - 0
liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/java/com/yomahub/liteflow/test/script/multi/language/cmp/ACmp.java

@@ -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.script.multi.language.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!");
+	}
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/java/com/yomahub/liteflow/test/script/multi/language/cmp/BCmp.java

@@ -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.script.multi.language.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!");
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/java/com/yomahub/liteflow/test/script/multi/language/cmp/CCmp.java

@@ -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.script.multi.language.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!");
+	}
+
+}

+ 1 - 0
liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/resources/multiLanguage/application.properties

@@ -0,0 +1 @@
+liteflow.rule-source=multiLanguage/flow.xml

+ 42 - 0
liteflow-testcase-el/liteflow-testcase-el-script-multi-language-springboot/src/test/resources/multiLanguage/flow.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<flow>
+    <nodes>
+        <node id="s1" name="groovy脚本" type="script" language="groovy">
+            <![CDATA[
+                class Student {
+                    int studentID
+                    String studentName
+                }
+
+                Student student = new Student()
+                student.studentID = 100301
+                student.studentName = "张三"
+                defaultContext.setData("student", student)
+
+                def a = 3
+                def b = 2
+                defaultContext.setData("s1", a * b)
+            ]]>
+        </node>
+
+        <node id="s2" name="js脚本" type="script" language="js">
+            <![CDATA[
+                var student = defaultContext.getData("student");
+                student.studentID = 10032;
+            ]]>
+        </node>
+
+        <node id="s3" name="python脚本" type="script" language="python">
+            <![CDATA[
+                a = 3
+                s1 = defaultContext.getData("s1")
+                defaultContext.setData("s1",s1*a)
+            ]]>
+        </node>
+    </nodes>
+
+    <chain name="chain1">
+        THEN(a, s1, b, s2, c, s3);
+    </chain>
+
+</flow>

+ 2 - 2
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/catchcase/CatchELSpringbootTest.java

@@ -46,14 +46,14 @@ public class CatchELSpringbootTest extends BaseTest {
     @Test
     public void testCatch3() throws Exception{
         LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg");
-        Assert.assertFalse(response.isSuccess());
+        Assert.assertTrue(response.isSuccess());
         Assert.assertEquals("a", response.getExecuteStepStrWithoutTime());
     }
 
     @Test
     public void testCatch4() throws Exception{
         LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg");
-        Assert.assertFalse(response.isSuccess());
+        Assert.assertTrue(response.isSuccess());
         Assert.assertEquals("LOOP_3==>a==>b==>a==>b==>a==>b", response.getExecuteStepStrWithoutTime());
     }
 }

+ 2 - 1
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/monitorFile/application.properties

@@ -1,2 +1,3 @@
-liteflow.rule-source=monitorFile/flow.el.xml
+#???monitorFile??????rule.xml???????????????????????
+liteflow.rule-source=monitorFile/rule.xml
 liteflow.enable-monitor-file=true

+ 1 - 0
liteflow-testcase-el/pom.xml

@@ -32,6 +32,7 @@
         <module>liteflow-testcase-el-apollo-springboot</module>
         <module>liteflow-testcase-el-script-python-springboot</module>
         <module>liteflow-testcase-el-script-lua-springboot</module>
+        <module>liteflow-testcase-el-script-multi-language-springboot</module>
     </modules>
 
     <build>