如何使用反射从外部 JAR 文件中检索一些资源

How to retrieve some resources from external JAR file using reflections

好的,我知道这里已经发布了类似的问题,事实上,我的解决方案就是从他们那里得到的。

我的想法是拥有一些模块(模块是 JAR 文件内文件夹中的一组 XML 文件),用户可以将其添加到应用程序中。这意味着用户可以将一些 jar 文件放在预定义的文件夹中,并且该 JAR 文件中的所有资源都必须可供应用程序使用。为此,我需要从外部文件夹加载所有 JAR,并将 XML 作为资源检索。 JAR文件,通常没有任何class文件,但也许将来会有。

该应用程序还有一个 "default" 模块,该模块已位于其资源文件夹中。该模块工作正常,我可以使用 Reflections 列出其中的所有 XML。

我使用反射检索所有 XML 文件的代码非常简单:

    final Set<String> resources = new Reflections(CustomPath.MODULES_FOLDER, new ResourcesScanner()).getResources(Pattern
            .compile(".*\.xml"));

returns 一组类似于 modules_folder/module_name/file1.xml 的字符串。

加载 Jar 文件的代码使用 URLClassLoader:

Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
        method.setAccessible(true); // promote the method to public access.
        method.invoke(loader, new Object[] { url });

据我所知,这些资源可从 URLClassLoader 获得。事实上,我可以这样做:

URLClassLoader.getSystemResource("modules_folder/module_name/file1.xml").

文件已加载,如果我输入无效路径,则会抛出错误。我还需要知道未预定义的 'module_name' 。那就不是办法了。

如果我运行再次使用反射获取资源的方法,它只会获取项目资源文件夹中的文件。未检索到 JAR 中的任何资源。

然后,我不明白为什么反射无法从已经加载的 JAR 文件中获取文件。我不确定 Reflections 是否出于任何原因无法访问 URLCLassLoader,或者必须以不同的方式使用它。

问题是...为什么 Reflections 无法访问在 运行 时加载的 JAR 中的资源?如果这是一个限制,那么在外部 JAR 文件中没有任何 Java classes 的情况下,最好的方法是什么?

好的,那就把最后的结果作为以后的参考。我的问题是 new Reflections(CustomPath.MODULES_FOLDER, new ResourcesScanner()) 的默认构造函数没有访问 URLClassLoader。那么它不可能得到我要找的资源。一种解决方案是使用 ConfigurationBuilder 并包括我需要的所有 ClassLoader。

final ConfigurationBuilder builder = new ConfigurationBuilder();
builder.addUrls(ClasspathHelper.forPackage(PathManager.MODULES_FOLDER, ClassLoader.getSystemClassLoader(),
            ClasspathHelper.contextClassLoader(), ClasspathHelper.staticClassLoader()));
builder.addScanners(new ResourcesScanner());
final Reflections reflections = new Reflections(builder);
final Set<String> resources = reflections.getResources(Pattern.compile(".*\.xml"));

正如在前面的代码中所看到的,我将 ClassLoader.getSystemClassLoader() 添加到构建器中,这个加载器就是我用来加载 Jar 文件的加载器。