支持绝对路径的模糊匹配
This commit is contained in:
parent
9fa94af5a8
commit
70954b4ae2
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 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;
|
||||
|
||||
// 匹配表达式
|
||||
String expr = pathExpr.replaceAll("/\\*\\.", "/[^\\.]*\\.");
|
||||
expr = expr.replaceAll("/\\*\\*/", "(/[^/]*)*/");
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
// 确定目录
|
||||
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 sufIdx2 = sufIdx;
|
||||
String suf2 = suf;
|
||||
|
||||
// 匹配表达式
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
liteflow.rule-source=/usr/local/flow.el.xml
|
||||
liteflow.rule-source=/usr/local/flow.el.xml
|
||||
#liteflow.rule-source=/usr/**/*.xml
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
|
||||
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中,文件目录支持绝对路径的模糊匹配,也可以将此文件移入任意/usr/**/*.xml中-->
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
WHEN(a,b,c);
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
liteflow.rule-source=/usr/local/flow.el.xml
|
||||
liteflow.rule-source=/usr/local/flow.el.xml
|
||||
#liteflow.rule-source=/usr/**/*.xml
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
|
||||
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中,文件目录支持绝对路径的模糊匹配,也可以将此文件移入任意/usr/**/*.xml中-->
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
WHEN(a,b,c);
|
||||
|
|
|
@ -23,6 +23,7 @@ public class AbsoluteConfigPathTest extends BaseTest {
|
|||
public static void init() {
|
||||
LiteflowConfig config = new LiteflowConfig();
|
||||
config.setRuleSource("/usr/local/flow2.xml");
|
||||
// config.setRuleSource("/usr/**/*.xml");
|
||||
flowExecutor = FlowExecutorHolder.loadInstance(config);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
|
||||
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中,文件目录支持绝对路径的模糊匹配,也可以将此文件移入任意/usr/**/*.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>
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
liteflow.rule-source=/usr/local/flow.el.xml
|
||||
liteflow.rule-source=/usr/local/flow.el.xml
|
||||
#liteflow.rule-source=/usr/**/*.xml
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
|
||||
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中,文件目录支持绝对路径的模糊匹配,也可以将此文件移入任意/usr/**/*.xml中-->
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
WHEN(a,b,c);
|
||||
|
|
|
@ -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,2 @@
|
|||
liteflow.rule-source=/usr/local/flow.el.xml
|
||||
liteflow.rule-source=/usr/local/flow.el.xml
|
||||
#liteflow.rule-source=/usr/**/*.xml
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
|
||||
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中,文件目录支持绝对路径的模糊匹配,也可以将此文件移入任意/usr/**/*.xml中-->
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
WHEN(a,b,c);
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
liteflow.rule-source=monitorFile/flow.el.xml
|
||||
#liteflow.rule-source=/usr/**/*.xml
|
||||
liteflow.enable-monitor-file=true
|
|
@ -17,6 +17,10 @@
|
|||
<property name="ruleSource" value="/usr/local/flow.el.xml"/>
|
||||
</bean>
|
||||
|
||||
<!-- <bean id="liteflowConfig" class="com.yomahub.liteflow.property.LiteflowConfig">-->
|
||||
<!-- <property name="ruleSource" value="/usr/**/*.xml"/>-->
|
||||
<!-- </bean>-->
|
||||
|
||||
<bean id="flowExecutor" class="com.yomahub.liteflow.core.FlowExecutor">
|
||||
<constructor-arg name="liteflowConfig" ref="liteflowConfig"/>
|
||||
</bean>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.el.xml中-->
|
||||
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.el.xml中,文件目录支持绝对路径的模糊匹配,也可以将此文件移入任意/usr/**/*.xml中-->
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
WHEN(a,b,c);
|
||||
|
|
Loading…
Reference in New Issue