如何从Java应用程序中加载的jar文件中加载资源?

时间:2019-03-24 20:53:45

标签: java

因此,我有一个主应用程序,应加载一个包含代码和其他资源(即:jar文件,文本文件,java属性等)的jar。我使用:

JarFile jar  = new JarFile(jar);
Enumeration<JarEntry> entries = jar.entries();

int URLsize = 1;
while (entries.hasMoreElements())
    if (entries.nextElement().getName().startsWith("foo/bar/foobar"))
        URLsize++;

entries = jar.entries();

URL[] urls = new URL[URLsize];
urls[0] = patch.toURI().toURL();

int count = 1;
while (entries.hasMoreElements())
{
    JarEntry nextElement = entries.nextElement();
    if (nextElement.getName().startsWith("foo/bar/foobar"))
    {               
        urls[count] = new URL("jar:file:/"+ jar.getAbsolutePath() + "!/" + nextElement.getName());

        count++;
    }
}

加载jar的资源,以及URLClassLoader加上一些反射以将所有资源聚集在一起并执行jar的主类,如下所示:

URLClassLoader loader = new URLClassLoader (urls);
Thread.currentThread().setContextClassLoader(loader);

Class<?> jarC = Class.forName ("foo.bar.barfoo.Main", true, loader);
Constructor<?> cons = jarC.getConstructor(String.class, String.class, Properties.class, Properties.class, String[].class);
Object instance = cons.newInstance (systemPath, programPath, config, some_data, args);

Method method = jarC.getMethod ("Main");

method.invoke (instance);

现在的问题是,当我尝试从jar内的程序包(例如:/ foo / bar / foobar)中加载一堆文件(资源)时,在加载的jar的代码内会抛出NullPointerException

private static InputStream getResourceAsStream(String resource) {       
        try {       
            return Thread.currentThread().getContextClassLoader().getResource(resource).openStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

这就是我尝试获取包的方法,而不是使用BufferedReaderInputStreamReader进行解析以获取包内每个资源的名称。 好的,也许有点太详细了(这只是我使用getResourceAsStream方法的一种方式),但我希望我能使自己理解,ContextClassLoader不包含我在应用程序中加载的资源在自己内部运行此jar,那么该怎么做才能从已加载的jar中获取这些内容?

编辑:调用getResourceAsStream方法:

private static List<String> getResourceFiles(String path) throws IOException {
    List<String> filenames = new ArrayList<>();

    try (
            InputStream in = getResourceAsStream(path);
            BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
        String resource;

        while ((resource = br.readLine()) != null) {
            filenames.add(resource);
        }
    }

    return filenames;
}

调用getResourceFiles方法的地方:

List<String> names = Foo.getResourceFiles("/foo/bar/foobar");

1 个答案:

答案 0 :(得分:1)

您为什么还要做所有这一切?为什么不将URL从JAR添加到URLClassLoader?

例如

URLClassLoader loader = new URLClassLoader(new File(jar).toURI().toURL());

另外,您可能应该使URLClassLoader将当前的类加载器作为父类,例如

URLClassLoader loader = new URLClassLoader(new File(jar).toURI().toURL(), Thread.currentThread().getContextClassLoader());