Browse Source

!240 支持绝对路径的模糊匹配
Merge pull request !240 from Rain/dev

铂赛东 1 year ago
parent
commit
daf51793fc
23 changed files with 383 additions and 82 deletions
  1. 5 3
      liteflow-core/src/main/java/com/yomahub/liteflow/spi/local/LocalPathContentParser.java
  2. 73 0
      liteflow-core/src/main/java/com/yomahub/liteflow/util/PathMatchUtil.java
  3. 45 38
      liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/PathsUtils.java
  4. 5 2
      liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringPathContentParser.java
  5. 35 5
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java
  6. 1 1
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties
  7. 1 1
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml
  8. 35 5
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java
  9. 1 1
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties
  10. 1 1
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml
  11. 45 7
      liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java
  12. 7 1
      liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml
  13. 35 4
      liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java
  14. 1 1
      liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties
  15. 1 1
      liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml
  16. 35 4
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java
  17. 16 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java
  18. 1 1
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties
  19. 1 1
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml
  20. 1 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/monitorFile/application.properties
  21. 36 3
      liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java
  22. 1 1
      liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml
  23. 1 1
      liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml

+ 5 - 3
liteflow-core/src/main/java/com/yomahub/liteflow/spi/local/LocalPathContentParser.java

@@ -9,6 +9,7 @@ import cn.hutool.core.util.ClassLoaderUtil;
 import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.exception.ConfigErrorException;
 import com.yomahub.liteflow.spi.PathContentParser;
+import com.yomahub.liteflow.util.PathMatchUtil;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -24,10 +25,11 @@ public class LocalPathContentParser implements PathContentParser {
 		if (CollectionUtil.isEmpty(pathList)) {
 			throw new ConfigErrorException("rule source must not be null");
 		}
+		List<String> absolutePathList = PathMatchUtil.searchAbsolutePath(pathList);
 
 		List<String> contentList = new ArrayList<>();
 
-		for (String path : pathList) {
+		for (String path : absolutePathList) {
 			if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)) {
 				path = FILE_URL_PREFIX + path;
 			}
@@ -50,10 +52,10 @@ public class LocalPathContentParser implements PathContentParser {
 		if (CollectionUtil.isEmpty(pathList)) {
 			throw new ConfigErrorException("rule source must not be null");
 		}
-
+		List<String> absolutePathList = PathMatchUtil.searchAbsolutePath(pathList);
 		List<String> result = new ArrayList<>();
 
-		for (String path : pathList) {
+		for (String path : absolutePathList) {
 			if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)) {
 				path = FILE_URL_PREFIX + path;
 				result.add(new FileResource(path).getFile().getAbsolutePath());

+ 73 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/util/PathMatchUtil.java

@@ -0,0 +1,73 @@
+package com.yomahub.liteflow.util;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.text.AntPathMatcher;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 用于获取模糊匹配的路径
+ *
+ * @author Rain
+ * @since 2.11.1
+ */
+public class PathMatchUtil {
+
+    public static List<String> searchAbsolutePath(List<String> pathList) {
+
+        List<String> absolutePathList = new ArrayList<>();
+
+        for (String path : pathList) {
+            // 只对绝对路径进行处理
+            if(FileUtil.isAbsolutePath(path)) {
+                if(!path.contains("*")) {
+                    absolutePathList.add(path);
+                }
+                else {
+                    String[] pathSegments = path.split("/");
+                    StringBuilder baseDir = new StringBuilder();
+
+                    // 找到最大基础路径
+                    for(int i = 0; i < pathSegments.length; i ++) {
+                        if(!pathSegments[i].contains("*")) {
+                            baseDir.append(pathSegments[i]).append(File.separator);
+                        } else {
+                            baseDir.deleteCharAt(baseDir.length() - 1);
+                            searchAbsolutePath(baseDir.toString(), path, absolutePathList);
+                            break;
+                        }
+                    }
+                }
+            } else {
+                absolutePathList.add(path);
+            }
+        }
+        // 路径去重
+        List<String> newAbsolutePathList = absolutePathList.stream()
+                .distinct()
+                .collect(Collectors.toList());
+        return newAbsolutePathList;
+    }
+
+    private static void searchAbsolutePath(String baseDir, String path, List<String> absolutePathList) {
+        AntPathMatcher pathMatcher = new AntPathMatcher();
+        File dir = new File(baseDir);
+        File[] files = dir.listFiles();
+
+        if (files != null) {
+            for (File file : files) {
+                if (file.isDirectory()) {
+                    searchAbsolutePath(file.getAbsolutePath(), path, absolutePathList);
+                } else {
+                    String absolutePath = file.getAbsolutePath().replace("\\", "/");
+                    if (pathMatcher.match(path, absolutePath)) {
+                        absolutePathList.add(absolutePath);
+                    }
+                }
+            }
+        }
+    }
+}

+ 45 - 38
liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/PathsUtils.java

@@ -1,8 +1,11 @@
 package com.yomahub.liteflow.solon.config;
 
+import cn.hutool.core.io.FileUtil;
+import com.yomahub.liteflow.util.PathMatchUtil;
 import org.noear.solon.core.util.ScanUtil;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.regex.Pattern;
@@ -17,51 +20,55 @@ public class PathsUtils {
 
 	public static Collection<String> resolvePaths(String pathExpr) {
 		List<String> paths = new ArrayList<>();
+		if(!FileUtil.isAbsolutePath(pathExpr)) {
+			if (pathExpr.contains("/*") == false) { // 说明没有*符
+				paths.add(pathExpr);
+				return paths;
+			}
 
-		if (pathExpr.contains("/*") == false) { // 说明没有*符
-			paths.add(pathExpr);
-			return paths;
-		}
-
-		// 确定目录
-		int dirIdx = pathExpr.indexOf("/*");
-		String dir = pathExpr.substring(0, dirIdx);
+			// 确定目录
+			int dirIdx = pathExpr.indexOf("/*");
+			String dir = pathExpr.substring(0, dirIdx);
 
-		// 确定后缀
-		int sufIdx = pathExpr.lastIndexOf(".");
-		String suf = null;
-		if (sufIdx > 0) {
-			suf = pathExpr.substring(sufIdx);
-			if (suf.contains("*")) {
-				sufIdx = -1;
-				suf = null;
+			// 确定后缀
+			int sufIdx = pathExpr.lastIndexOf(".");
+			String suf = null;
+			if (sufIdx > 0) {
+				suf = pathExpr.substring(sufIdx);
+				if (suf.contains("*")) {
+					sufIdx = -1;
+					suf = null;
+				}
 			}
-		}
 
-		int sufIdx2 = sufIdx;
-		String suf2 = suf;
+			int sufIdx2 = sufIdx;
+			String suf2 = suf;
 
-		// 匹配表达式
-		String expr = pathExpr.replaceAll("/\\*\\.", "/[^\\.]*\\.");
-		expr = expr.replaceAll("/\\*\\*/", "(/[^/]*)*/");
+			// 匹配表达式
+			String expr = pathExpr.replaceAll("/\\*\\.", "/[^\\.]*\\.");
+			expr = expr.replaceAll("/\\*\\*/", "(/[^/]*)*/");
 
-		Pattern pattern = Pattern.compile(expr);
-
-		ScanUtil.scan(dir, n -> {
-			// 进行后缀过滤,相对比较快
-			if (sufIdx2 > 0) {
-				return n.endsWith(suf2);
-			}
-			else {
-				return true;
-			}
-		}).forEach(uri -> {
-			// 再进行表达式过滤
-			if (pattern.matcher(uri).find()) {
-				paths.add(uri);
-			}
-		});
+			Pattern pattern = Pattern.compile(expr);
 
+			List<String> finalPaths = paths;
+			ScanUtil.scan(dir, n -> {
+				// 进行后缀过滤,相对比较快
+				if (sufIdx2 > 0) {
+					return n.endsWith(suf2);
+				}
+				else {
+					return true;
+				}
+			}).forEach(uri -> {
+				// 再进行表达式过滤
+				if (pattern.matcher(uri).find()) {
+					finalPaths.add(uri);
+				}
+			});
+		} else {
+			String[] pathExprs = pathExpr.split(",");
+			paths = PathMatchUtil.searchAbsolutePath(Arrays.asList(pathExprs));
+		}
 		return paths;
 	}
 

+ 5 - 2
liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringPathContentParser.java

@@ -10,6 +10,7 @@ import cn.hutool.core.util.CharsetUtil;
 import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.exception.ConfigErrorException;
 import com.yomahub.liteflow.spi.PathContentParser;
+import com.yomahub.liteflow.util.PathMatchUtil;
 import org.springframework.core.io.Resource;
 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 import org.springframework.core.io.support.ResourcePatternResolver;
@@ -26,7 +27,8 @@ public class SpringPathContentParser implements PathContentParser {
 
 	@Override
 	public List<String> parseContent(List<String> pathList) throws Exception {
-		List<Resource> allResource = getResources(pathList);
+		List<String> absolutePathList = PathMatchUtil.searchAbsolutePath(pathList);
+		List<Resource> allResource = getResources(absolutePathList);
 
 		// 转换成内容List
 		List<String> contentList = new ArrayList<>();
@@ -42,7 +44,8 @@ public class SpringPathContentParser implements PathContentParser {
 
 	@Override
 	public List<String> getFileAbsolutePath(List<String> pathList) throws Exception {
-		List<Resource> allResource = getResources(pathList);
+		List<String> absolutePathList = PathMatchUtil.searchAbsolutePath(pathList);
+		List<Resource> allResource = getResources(absolutePathList);
 
 		return StreamUtil.of(allResource)
 			// 过滤非 file 类型 Resource

+ 35 - 5
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java

@@ -1,9 +1,15 @@
 package com.yomahub.liteflow.test.absoluteConfigPath;
 
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.CharsetUtil;
 import com.yomahub.liteflow.core.FlowExecutor;
 import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
 import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -24,21 +30,45 @@ import javax.annotation.Resource;
  * @since 2.6.4
  */
 @ExtendWith(SpringExtension.class)
-@TestPropertySource(value = "classpath:/absoluteConfigPath/application.properties")
 @SpringBootTest(classes = AbsoluteConfigPathELDeclMultiSpringbootTest.class)
 @EnableAutoConfiguration
 @ComponentScan({ "com.yomahub.liteflow.test.absoluteConfigPath.cmp" })
 public class AbsoluteConfigPathELDeclMultiSpringbootTest extends BaseTest {
 
-	private final Logger log = LoggerFactory.getLogger(this.getClass());
-
 	@Resource
 	private FlowExecutor flowExecutor;
 
 	@Test
 	public void testAbsoluteConfig() throws Exception {
-		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
-		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml");
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@Test
+	public void testAbsolutePathMatch() throws Exception {
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml");
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@BeforeAll
+	public static void createFiles() {
+		String filePath = "C:/LiteFlow/Test/a/b/c";
+		String content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><flow><chain name=\"chain1\">WHEN(a, b, c);</chain></flow>";
+		FileUtil.mkdir(filePath);
+		FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8);
+	}
+
+	@AfterAll
+	public static void removeFiles() {
+		FileUtil.del("C:/LiteFlow");
 	}
 
 }

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties

@@ -1 +1 @@
-liteflow.rule-source=/usr/local/flow.el.xml
+liteflow.rule-source=C:/LiteFlow/Test/a/b/c/flow.el.xml

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
+<!--这里只是内容,文件目录支持绝对路径的模糊匹配-->
 <flow>
     <chain name="chain1">
         WHEN(a,b,c);

+ 35 - 5
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java

@@ -1,9 +1,15 @@
 package com.yomahub.liteflow.test.absoluteConfigPath;
 
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.CharsetUtil;
 import com.yomahub.liteflow.core.FlowExecutor;
 import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
 import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -24,21 +30,45 @@ import javax.annotation.Resource;
  * @since 2.6.4
  */
 @ExtendWith(SpringExtension.class)
-@TestPropertySource(value = "classpath:/absoluteConfigPath/application.properties")
 @SpringBootTest(classes = AbsoluteConfigPathELDeclSpringbootTest.class)
 @EnableAutoConfiguration
 @ComponentScan({ "com.yomahub.liteflow.test.absoluteConfigPath.cmp" })
 public class AbsoluteConfigPathELDeclSpringbootTest extends BaseTest {
 
-	private final Logger log = LoggerFactory.getLogger(this.getClass());
-
 	@Resource
 	private FlowExecutor flowExecutor;
 
 	@Test
 	public void testAbsoluteConfig() throws Exception {
-		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
-		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml");
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@Test
+	public void testAbsolutePathMatch() throws Exception {
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml");
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@BeforeAll
+	public static void createFiles() {
+		String filePath = "C:/LiteFlow/Test/a/b/c";
+		String content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><flow><chain name=\"chain1\">WHEN(a, b, c);</chain></flow>";
+		FileUtil.mkdir(filePath);
+		FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8);
+	}
+
+	@AfterAll
+	public static void removeFiles() {
+		FileUtil.del("C:/LiteFlow");
 	}
 
 }

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties

@@ -1 +1 @@
-liteflow.rule-source=/usr/local/flow.el.xml
+liteflow.rule-source=C:/LiteFlow/Test/a/b/c/flow.el.xml

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
+<!--这里只是内容,文件目录支持绝对路径的模糊匹配-->
 <flow>
     <chain name="chain1">
         WHEN(a,b,c);

+ 45 - 7
liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java

@@ -1,10 +1,14 @@
 package com.yomahub.liteflow.test.absoluteConfigPath;
 
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.CharsetUtil;
 import com.yomahub.liteflow.core.FlowExecutor;
 import com.yomahub.liteflow.core.FlowExecutorHolder;
 import com.yomahub.liteflow.flow.LiteflowResponse;
 import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
 import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -19,17 +23,51 @@ public class AbsoluteConfigPathTest extends BaseTest {
 
 	private static FlowExecutor flowExecutor;
 
+
+	@Test
+	public void testAbsoluteConfig() throws Exception {
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml");
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@Test
+	public void testAbsolutePathMatch() throws Exception {
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml");
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
 	@BeforeAll
-	public static void init() {
+	public static void createFiles() {
+		String filePath = "C:/LiteFlow/Test/a/b/c";
+		String content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+				"<flow>\n" +
+				"<nodes>\n" +
+				"    <node id=\"a\" class=\"com.yomahub.liteflow.test.absoluteConfigPath.cmp.ACmp\"/>\n" +
+				"    <node id=\"b\" class=\"com.yomahub.liteflow.test.absoluteConfigPath.cmp.BCmp\"/>\n" +
+				"    <node id=\"c\" class=\"com.yomahub.liteflow.test.absoluteConfigPath.cmp.CCmp\"/>\n" +
+				"</nodes>\n" +
+				"\n" +
+				"<chain name=\"chain1\">\n" +
+				"    WHEN(a,b,c);\n" +
+				"</chain>\n" +
+				"</flow>";
+		FileUtil.mkdir(filePath);
+		FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8);
 		LiteflowConfig config = new LiteflowConfig();
-		config.setRuleSource("/usr/local/flow2.xml");
+		config.setRuleSource("absoluteConfigPath/flow.el.xml");
 		flowExecutor = FlowExecutorHolder.loadInstance(config);
 	}
 
-	@Test
-	public void testAbsoluteConfig() throws Exception {
-		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
-		Assertions.assertTrue(response.isSuccess());
+	@AfterAll
+	public static void removeFiles() {
+		FileUtil.del("C:/LiteFlow");
 	}
-
 }

+ 7 - 1
liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml

@@ -1,6 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
+<!--这里只是内容,文件目录支持绝对路径的模糊匹配-->
 <flow>
+    <nodes>
+        <node id="a" class="com.yomahub.liteflow.test.absoluteConfigPath.cmp.ACmp"/>
+        <node id="b" class="com.yomahub.liteflow.test.absoluteConfigPath.cmp.BCmp"/>
+        <node id="c" class="com.yomahub.liteflow.test.absoluteConfigPath.cmp.CCmp"/>
+    </nodes>
+
     <chain name="chain1">
         WHEN(a,b,c);
     </chain>

+ 35 - 4
liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java

@@ -1,9 +1,15 @@
 package com.yomahub.liteflow.test.absoluteConfigPath;
 
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.CharsetUtil;
 import com.yomahub.liteflow.core.FlowExecutor;
 import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
 import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.noear.solon.annotation.Inject;
@@ -19,18 +25,43 @@ import org.slf4j.LoggerFactory;
  * @since 2.6.4
  */
 @ExtendWith(SolonJUnit5Extension.class)
-@TestPropertySource("classpath:/absoluteConfigPath/application.properties")
 public class AbsoluteConfigPathELSpringbootTest extends BaseTest {
 
-	private final Logger log = LoggerFactory.getLogger(this.getClass());
 
 	@Inject
 	private FlowExecutor flowExecutor;
 
 	@Test
 	public void testAbsoluteConfig() throws Exception {
-		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
-		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml");
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@Test
+	public void testAbsolutePathMatch() throws Exception {
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml");
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@BeforeAll
+	public static void createFiles() {
+		String filePath = "C:/LiteFlow/Test/a/b/c";
+		String content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><flow><chain name=\"chain1\">WHEN(a, b, c);</chain></flow>";
+		FileUtil.mkdir(filePath);
+		FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8);
+	}
+
+	@AfterAll
+	public static void removeFiles() {
+		FileUtil.del("C:/LiteFlow");
 	}
 
 }

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties

@@ -1 +1 @@
-liteflow.rule-source=/usr/local/flow.el.xml
+liteflow.rule-source=C:/LiteFlow/Test/a/b/c/flow.el.xml

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
+<!--这里只是内容,文件目录支持绝对路径的模糊匹配-->
 <flow>
     <chain name="chain1">
         WHEN(a,b,c);

+ 35 - 4
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java

@@ -1,9 +1,15 @@
 package com.yomahub.liteflow.test.absoluteConfigPath;
 
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.CharsetUtil;
 import com.yomahub.liteflow.core.FlowExecutor;
 import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
 import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -20,21 +26,46 @@ import javax.annotation.Resource;
  * @author Bryan.Zhang
  * @since 2.6.4
  */
-@TestPropertySource(value = "classpath:/absoluteConfigPath/application.properties")
 @SpringBootTest(classes = AbsoluteConfigPathELSpringbootTest.class)
 @EnableAutoConfiguration
 @ComponentScan({ "com.yomahub.liteflow.test.absoluteConfigPath.cmp" })
 public class AbsoluteConfigPathELSpringbootTest extends BaseTest {
 
-	private final Logger log = LoggerFactory.getLogger(this.getClass());
 
 	@Resource
 	private FlowExecutor flowExecutor;
 
 	@Test
 	public void testAbsoluteConfig() throws Exception {
-		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
-		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml");
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@Test
+	public void testAbsolutePathMatch() throws Exception {
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml");
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@BeforeAll
+	public static void createFiles() {
+		String filePath = "C:/LiteFlow/Test/a/b/c";
+		String content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><flow><chain name=\"chain1\">WHEN(a, b, c);</chain></flow>";
+		FileUtil.mkdir(filePath);
+		FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8);
+	}
+
+	@AfterAll
+	public static void removeFiles() {
+		FileUtil.del("C:/LiteFlow");
 	}
 
 }

+ 16 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java

@@ -38,6 +38,22 @@ public class MonitorFileELSpringbootTest extends BaseTest {
 		Assertions.assertEquals("a==>c==>b", response.getExecuteStepStr());
 	}
 
+    /**
+     * 对绝对路径模糊匹配功能的测试
+     */
+    @Test
+    public void testMonitorAbsolutePath() throws Exception {
+        String absolutePath = "/your/path/dir";
+        FileUtil.writeString("<?xml version=\"1.0\" encoding=\"UTF-8\"?><flow><chain name=\"chain1\">THEN(a, b, c);</chain></flow>", new File(absolutePath), CharsetUtil.CHARSET_UTF_8);
+        String content = FileUtil.readUtf8String(absolutePath);
+        String newContent = content.replace("THEN(a, b, c);", "THEN(a, c, b);");
+        Thread.sleep(1000);
+        FileUtil.writeString(newContent, new File(absolutePath), CharsetUtil.CHARSET_UTF_8);
+        Thread.sleep(3000);
+        LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+        Assertions.assertEquals("a==>c==>b", response.getExecuteStepStr());
+    }
+
     /**
      * 测试文件变更,但是 EL 规则错误情况
      * 输出 ERROR 日志异常信息,但是不会停止监听线程,当下一次变更正确后替换为新规则

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

@@ -1 +1 @@
-liteflow.rule-source=/usr/local/flow.el.xml
+liteflow.rule-source=C:/LiteFlow/Test/a/b/c/flow.el.xml

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
+<!--这里只是内容,文件目录支持绝对路径的模糊匹配-->
 <flow>
     <chain name="chain1">
         WHEN(a,b,c);

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

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

+ 36 - 3
liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java

@@ -1,9 +1,15 @@
 package com.yomahub.liteflow.test.absoluteConfigPath;
 
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.CharsetUtil;
 import com.yomahub.liteflow.core.FlowExecutor;
 import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
 import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.springframework.test.context.ContextConfiguration;
@@ -25,9 +31,36 @@ public class AbsoluteConfigPathELSpringTest extends BaseTest {
 	private FlowExecutor flowExecutor;
 
 	@Test
-	public void testAbsoluteConfig() {
-		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
-		Assertions.assertTrue(response.isSuccess());
+	public void testAbsoluteConfig() throws Exception {
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml");
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@Test
+	public void testAbsolutePathMatch() throws Exception {
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml");
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@BeforeAll
+	public static void createFiles() {
+		String filePath = "C:/LiteFlow/Test/a/b/c";
+		String content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><flow><chain name=\"chain1\">WHEN(a, b, c);</chain></flow>";
+		FileUtil.mkdir(filePath);
+		FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8);
+	}
+
+	@AfterAll
+	public static void removeFiles() {
+		FileUtil.del("C:/LiteFlow");
 	}
 
 }

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml

@@ -14,7 +14,7 @@
     <bean class="com.yomahub.liteflow.spring.ComponentScanner"/>
 
     <bean id="liteflowConfig" class="com.yomahub.liteflow.property.LiteflowConfig">
-        <property name="ruleSource" value="/usr/local/flow.el.xml"/>
+        <property name="ruleSource" value="C:/LiteFlow/Test/a/b/c/flow.el.xml"/>
     </bean>
 
     <bean id="flowExecutor" class="com.yomahub.liteflow.core.FlowExecutor">

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.el.xml中-->
+<!--这里只是内容,文件目录支持绝对路径的模糊匹配-->
 <flow>
     <chain name="chain1">
         WHEN(a,b,c);