从另一个 jar 文件访问资源

2022-09-03 07:57:17

我有一个简单的结构:一个包含一批数据的数据jar文件,以及一个使用数据运行服务的service jar文件。为了使数据易于替换,我将它们分开,并且 service.jar 的类路径包含数据.jar所在的目录。

在服务.jar,我使用getResource来加载数据文件。如果数据文件直接位于文件夹中,则此方法有效,但当它们位于数据.jar内部时会失败;

此操作将失败:

all
+ globalclasspath
| + data.jar
|   + mine.properties
+ daemons
  + service.jar

jsvc -cp globalclasspath:daemons/service.jar (...)

MyClass.class.getClassLoader( ).getResource( "mine.properties" ); // <-- null

但这有效:

all
+ globalclasspath
| + mine.properties
+ daemons
  + service.jar

jsvc -cp globalclasspath:daemons/service.jar (...)

MyClass.class.getClassLoader( ).getResource( "mine.properties" ); // <-- not null

我不想更改类路径(除非我可以将其更改为不依赖于数据jar文件名称的通用代码),但我可以更改getResource字符串(我已经尝试了/data/mine.properties和/data.jar/mine.properties,但无济于事)。是否可以进行更改,以便可以从 jar 中加载资源?


答案 1

解决方案 1

使用类路径通配符。

jsvc -cp globalclasspath/*:daemons/service.jar (...)

请参阅“如何在类路径中使用通配符来添加多个 jar?"

解决方案 2

要读取 JAR 中不在类路径上的数据,请使用 URLClassLoader。一般的算法是这样的:

  1. 在目录中查找 JAR 的列表。globalclasspath
  2. 从此 JAR 列表中创建一个。URLClassLoader
  3. 从实例中查找所需的资源。URLClassLoader

为了在类路径上查找 JAR,我使用了 StackOverflow 文章“从类路径目录中获取资源列表”中的 ResourceList

public class MyClass {
    /**
     * Creates a {@code URLClassLoader} from JAR files found in the
     * globalclasspath directory, assuming that globalclasspath is in
     * {@code System.getProperty("java.class.path")}.
     */
    private static URLClassLoader createURLClassLoader() {
        Collection<String> resources = ResourceList.getResources(Pattern.compile(".*\\.jar"));
        Collection<URL> urls = new ArrayList<URL>();
        for (String resource : resources) {
            File file = new File(resource);
            // Ensure that the JAR exists
            // and is in the globalclasspath directory.
            if (file.isFile() && "globalclasspath".equals(file.getParentFile().getName())) {
                try {
                    urls.add(file.toURI().toURL());
                } catch (MalformedURLException e) {
                    // This should never happen.
                    e.printStackTrace();
                }
            }
        }
        return new URLClassLoader(urls.toArray(new URL[urls.size()]));
    }

    public static void main(String[] args) {
        URLClassLoader classLoader = createURLClassLoader();
        System.out.println(classLoader.getResource("mine.properties"));
    }
}

我运行了以下命令:

java -cp globalclasspath:daemons/service.jar MyClass

终端输出:

jar:file:/workspace/all/globalclasspath/data.jar!/mine.properties

答案 2

你有没有按照这里的建议尝试过:getResourceAsStream

how-to-a-read-file-from-jar-in-java


推荐