diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceFinder.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceFinder.java
index 7e95a9040..a24694dca 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceFinder.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceFinder.java
@@ -14,13 +14,16 @@ package org.dromara.hutool.core.io.resource;
import org.dromara.hutool.core.collection.iter.EnumerationIter;
import org.dromara.hutool.core.compress.ZipUtil;
+import org.dromara.hutool.core.exception.HutoolException;
import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.io.IoUtil;
+import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.net.url.URLUtil;
import org.dromara.hutool.core.text.AntPathMatcher;
import org.dromara.hutool.core.text.CharUtil;
import org.dromara.hutool.core.text.StrUtil;
+import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
@@ -59,14 +62,18 @@ public class ResourceFinder {
final MultiResource result = new MultiResource();
// 遍历根目录下所有资源,并过滤保留符合条件的资源
for (final Resource rootResource : ResourceUtil.getResources(rootDirPath, classLoader)) {
- if (URLUtil.isJarURL(rootResource.getUrl())) {
+ if (rootResource instanceof JarResource) {
+ // 在jar包中
try {
- result.addAll(findInJar(rootResource, subPattern));
+ result.addAll(findInJar((JarResource) rootResource, subPattern));
} catch (final IOException e) {
throw new IORuntimeException(e);
}
+ } else if (rootResource instanceof FileResource) {
+ // 文件夹中
+ result.addAll(findInDir((FileResource) rootResource, subPattern));
} else {
- result.addAll(findInDir(rootResource, subPattern));
+ throw new HutoolException("Unsupported resource type: {}", rootResource.getClass().getName());
}
}
@@ -81,12 +88,11 @@ public class ResourceFinder {
* @return 符合条件的资源
* @throws IOException IO异常
*/
- protected MultiResource findInJar(final Resource rootResource, final String subPattern) throws IOException {
+ protected MultiResource findInJar(final JarResource rootResource, final String subPattern) throws IOException {
final URL rootDirURL = rootResource.getUrl();
final URLConnection conn = rootDirURL.openConnection();
final JarFile jarFile;
- final String jarFileUrl;
String rootEntryPath;
final boolean closeJarFile;
@@ -98,7 +104,7 @@ public class ResourceFinder {
rootEntryPath = (jarEntry != null ? jarEntry.getName() : StrUtil.EMPTY);
closeJarFile = !jarCon.getUseCaches();
} else {
- //
+ // 去除子路径后重新获取jar文件
final String urlFile = rootDirURL.getFile();
try {
int separatorIndex = urlFile.indexOf(URLUtil.WAR_URL_SEPARATOR);
@@ -106,7 +112,7 @@ public class ResourceFinder {
separatorIndex = urlFile.indexOf(URLUtil.JAR_URL_SEPARATOR);
}
if (separatorIndex != -1) {
- jarFileUrl = urlFile.substring(0, separatorIndex);
+ final String jarFileUrl = urlFile.substring(0, separatorIndex);
rootEntryPath = urlFile.substring(separatorIndex + 2); // both separators are 2 chars
jarFile = ZipUtil.ofJar(jarFileUrl);
} else {
@@ -130,7 +136,7 @@ public class ResourceFinder {
if (entryPath.startsWith(rootEntryPath)) {
final String relativePath = entryPath.substring(rootEntryPath.length());
if (pathMatcher.match(subPattern, relativePath)) {
- result.add(new UrlResource(URLUtil.getURL(rootDirURL, relativePath)));
+ result.add(ResourceUtil.getResource(URLUtil.getURL(rootDirURL, relativePath)));
}
}
}
@@ -143,8 +149,23 @@ public class ResourceFinder {
return result;
}
- protected MultiResource findInDir(final Resource rootResource, final String subPattern) {
+ /**
+ * 遍历目录查找指定表达式匹配的文件列表
+ *
+ * @param resource 文件资源
+ * @param subPattern 子表达式
+ * @return 满足条件的文件
+ */
+ protected MultiResource findInDir(final FileResource resource, final String subPattern) {
+ final MultiResource result = new MultiResource();
+ final File rootDir = resource.getFile();
+ FileUtil.walkFiles(rootDir, (file -> {
+ if (pathMatcher.match(subPattern, file.getName())) {
+ result.add(new FileResource(file));
+ }
+ }));
+ return result;
}
/**
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceUtil.java
index 176a464d2..fd1c56fbb 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceUtil.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceUtil.java
@@ -17,6 +17,7 @@ import org.dromara.hutool.core.collection.iter.IterUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.lang.Assert;
+import org.dromara.hutool.core.net.url.UrlProtocolUtil;
import org.dromara.hutool.core.util.CharsetUtil;
import org.dromara.hutool.core.classloader.ClassLoaderUtil;
import org.dromara.hutool.core.text.StrUtil;
@@ -253,6 +254,11 @@ public class ResourceUtil {
* @since 6.0.0
*/
public static Resource getResource(final URL url) {
+ if(UrlProtocolUtil.isJarURL(url)){
+ return new JarResource(url);
+ } else if(UrlProtocolUtil.isFileURL(url)){
+ return new FileResource(url.getFile());
+ }
return new UrlResource(url);
}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/UrlResource.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/UrlResource.java
index 490aeffed..0a605eb0c 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/UrlResource.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/UrlResource.java
@@ -15,6 +15,7 @@ package org.dromara.hutool.core.io.resource;
import org.dromara.hutool.core.io.file.FileNameUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.net.url.URLUtil;
+import org.dromara.hutool.core.net.url.UrlProtocolUtil;
import org.dromara.hutool.core.util.ObjUtil;
import java.io.File;
@@ -64,7 +65,7 @@ public class UrlResource implements Resource, Serializable {
*/
public UrlResource(final URL url, final String name) {
this.url = url;
- if (null != url && URLUtil.URL_PROTOCOL_FILE.equals(url.getProtocol())) {
+ if (null != url && UrlProtocolUtil.URL_PROTOCOL_FILE.equals(url.getProtocol())) {
this.lastModified = FileUtil.file(url).lastModified();
}
this.name = ObjUtil.defaultIfNull(name, () -> (null != url ? FileNameUtil.getName(url.getPath()) : null));
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/net/url/URLUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/net/url/URLUtil.java
index 760455ba4..542c01de0 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/net/url/URLUtil.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/net/url/URLUtil.java
@@ -16,7 +16,6 @@ import org.dromara.hutool.core.classloader.ClassLoaderUtil;
import org.dromara.hutool.core.exception.HutoolException;
import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.io.IoUtil;
-import org.dromara.hutool.core.io.file.FileNameUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.io.resource.ResourceUtil;
import org.dromara.hutool.core.lang.Assert;
@@ -64,34 +63,6 @@ public class URLUtil {
* URL 前缀表示war: "war:"
*/
public static final String WAR_URL_PREFIX = "war:";
- /**
- * URL 协议表示文件: "file"
- */
- public static final String URL_PROTOCOL_FILE = "file";
- /**
- * URL 协议表示Jar文件: "jar"
- */
- public static final String URL_PROTOCOL_JAR = "jar";
- /**
- * URL 协议表示zip文件: "zip"
- */
- public static final String URL_PROTOCOL_ZIP = "zip";
- /**
- * URL 协议表示WebSphere文件: "wsjar"
- */
- public static final String URL_PROTOCOL_WSJAR = "wsjar";
- /**
- * URL 协议表示JBoss zip文件: "vfszip"
- */
- public static final String URL_PROTOCOL_VFSZIP = "vfszip";
- /**
- * URL 协议表示JBoss文件: "vfsfile"
- */
- public static final String URL_PROTOCOL_VFSFILE = "vfsfile";
- /**
- * URL 协议表示JBoss VFS资源: "vfs"
- */
- public static final String URL_PROTOCOL_VFS = "vfs";
/**
* Jar路径以及内部文件路径的分界符: "!/"
*/
@@ -429,50 +400,6 @@ public class URLUtil {
}
// endregion
- /**
- * 提供的URL是否为文件
- * 文件协议包括"file", "vfsfile" 或 "vfs".
- *
- * @param url {@link URL}
- * @return 是否为文件
- * @since 3.0.9
- */
- public static boolean isFileURL(final URL url) {
- Assert.notNull(url, "URL must be not null");
- final String protocol = url.getProtocol();
- return (URL_PROTOCOL_FILE.equals(protocol) || //
- URL_PROTOCOL_VFSFILE.equals(protocol) || //
- URL_PROTOCOL_VFS.equals(protocol));
- }
-
- /**
- * 提供的URL是否为jar包URL 协议包括: "jar", "zip", "vfszip" 或 "wsjar".
- *
- * @param url {@link URL}
- * @return 是否为jar包URL
- */
- public static boolean isJarURL(final URL url) {
- Assert.notNull(url, "URL must be not null");
- final String protocol = url.getProtocol();
- return (URL_PROTOCOL_JAR.equals(protocol) || //
- URL_PROTOCOL_ZIP.equals(protocol) || //
- URL_PROTOCOL_VFSZIP.equals(protocol) || //
- URL_PROTOCOL_WSJAR.equals(protocol));
- }
-
- /**
- * 提供的URL是否为Jar文件URL 判断依据为file协议且扩展名为.jar
- *
- * @param url the URL to check
- * @return whether the URL has been identified as a JAR file URL
- * @since 4.1
- */
- public static boolean isJarFileURL(final URL url) {
- Assert.notNull(url, "URL must be not null");
- return (URL_PROTOCOL_FILE.equals(url.getProtocol()) && //
- url.getPath().toLowerCase().endsWith(FileNameUtil.EXT_JAR));
- }
-
/**
* 从URL中获取流
*
@@ -704,7 +631,7 @@ public class URLUtil {
* @since 6.0.0
*/
public static long size(final URL url) {
- if (URLUtil.isFileURL(url)) {
+ if (UrlProtocolUtil.isFileOrVfsURL(url)) {
// 如果资源以独立文件形式存在,尝试获取文件长度
final File file = FileUtil.file(url);
final long length = file.length();
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/net/url/UrlProtocolUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/net/url/UrlProtocolUtil.java
new file mode 100644
index 000000000..f2b543c25
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/net/url/UrlProtocolUtil.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2023. looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * https://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.net.url;
+
+import org.dromara.hutool.core.io.file.FileNameUtil;
+import org.dromara.hutool.core.lang.Assert;
+
+import java.net.URL;
+
+public class UrlProtocolUtil {
+ /**
+ * URL 协议表示文件: "file"
+ */
+ public static final String URL_PROTOCOL_FILE = "file";
+ /**
+ * URL 协议表示Jar文件: "jar"
+ */
+ public static final String URL_PROTOCOL_JAR = "jar";
+ /**
+ * URL 协议表示zip文件: "zip"
+ */
+ public static final String URL_PROTOCOL_ZIP = "zip";
+ /**
+ * URL 协议表示WebSphere文件: "wsjar"
+ */
+ public static final String URL_PROTOCOL_WSJAR = "wsjar";
+ /**
+ * URL 协议表示JBoss zip文件: "vfszip"
+ */
+ public static final String URL_PROTOCOL_VFSZIP = "vfszip";
+ /**
+ * URL 协议表示JBoss文件: "vfsfile"
+ */
+ public static final String URL_PROTOCOL_VFSFILE = "vfsfile";
+ /**
+ * URL 协议表示JBoss VFS资源: "vfs"
+ */
+ public static final String URL_PROTOCOL_VFS = "vfs";
+
+ /**
+ * 提供的URL是否为文件
+ * 文件协议包括"file", "vfsfile" 或 "vfs".
+ *
+ * @param url {@link URL}
+ * @return 是否为文件
+ * @since 3.0.9
+ */
+ public static boolean isFileOrVfsURL(final URL url) {
+ Assert.notNull(url, "URL must be not null");
+ return isFileURL(url) || isVfsURL(url);
+ }
+
+ /**
+ * 提供的URL是否为文件
+ * 文件协议包括"file".
+ *
+ * @param url {@link URL}
+ * @return 是否为文件
+ * @since 6.0.0
+ */
+ public static boolean isFileURL(final URL url) {
+ Assert.notNull(url, "URL must be not null");
+ final String protocol = url.getProtocol();
+ return URL_PROTOCOL_FILE.equals(protocol);
+ }
+
+ /**
+ * 提供的URL是否为文件
+ * 文件协议包括"vfsfile" 或 "vfs".
+ *
+ * @param url {@link URL}
+ * @return 是否为文件
+ * @since 6.0.0
+ */
+ public static boolean isVfsURL(final URL url) {
+ Assert.notNull(url, "URL must be not null");
+ final String protocol = url.getProtocol();
+ return (URL_PROTOCOL_VFSFILE.equals(protocol) || //
+ URL_PROTOCOL_VFS.equals(protocol));
+ }
+
+ /**
+ * 提供的URL是否为jar包URL 协议包括: "jar", "zip", "vfszip" 或 "wsjar".
+ *
+ * @param url {@link URL}
+ * @return 是否为jar包URL
+ */
+ public static boolean isJarURL(final URL url) {
+ Assert.notNull(url, "URL must be not null");
+ final String protocol = url.getProtocol();
+ return (URL_PROTOCOL_JAR.equals(protocol) || //
+ URL_PROTOCOL_ZIP.equals(protocol) || //
+ URL_PROTOCOL_VFSZIP.equals(protocol) || //
+ URL_PROTOCOL_WSJAR.equals(protocol));
+ }
+
+ /**
+ * 提供的URL是否为Jar文件URL 判断依据为file协议且扩展名为.jar
+ *
+ * @param url the URL to check
+ * @return whether the URL has been identified as a JAR file URL
+ * @since 4.1
+ */
+ public static boolean isJarFileURL(final URL url) {
+ Assert.notNull(url, "URL must be not null");
+ return (URL_PROTOCOL_FILE.equals(url.getProtocol()) && //
+ url.getPath().toLowerCase().endsWith(FileNameUtil.EXT_JAR));
+ }
+}
diff --git a/hutool-setting/src/main/java/org/dromara/hutool/setting/props/Props.java b/hutool-setting/src/main/java/org/dromara/hutool/setting/props/Props.java
index b26a55b5b..97b0709de 100644
--- a/hutool-setting/src/main/java/org/dromara/hutool/setting/props/Props.java
+++ b/hutool-setting/src/main/java/org/dromara/hutool/setting/props/Props.java
@@ -190,7 +190,7 @@ public final class Props extends Properties implements TypeGetter
* @since 5.5.2
*/
public void load(final URL url) {
- load(new UrlResource(url));
+ load(ResourceUtil.getResource(url));
}
/**