16

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

在 service.jar 中,我使用 getResource 来加载数据文件。如果数据文件直接在文件夹中,则此方法有效,但在 data.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 中加载资源吗?

4

3 回答 3

5

解决方案 1

使用类路径通配符。

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

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

解决方案 2

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

  1. globalclasspath目录中找到 JAR 列表。
  2. URLClassLoader从此 JAR 列表创建一个。
  3. URLClassLoader从实例中查找您想要的资源。

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

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
于 2013-11-22T17:18:49.590 回答
2

您是否getResourceAsStream按照此处的建议尝试过:

如何从 jar-in-java 读取文件

于 2013-11-22T17:11:17.577 回答
-1

您现在可以使用maven-resources-pluginjar 在您的 jar 之间共享资源!

在源模块/jar 的 pom.xml 文件中,添加以下插件:

<artifactId>DATA_MODULE_NAME</artifactId>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
        </plugin>
    </plugins>
</build>

这将告诉 maven 将资源文件夹的内容与 jar 一起复制。

在要访问这些资源的模块中,将其添加到 pom 中的依赖项中:

<dependencies>
    <dependency>
        <groupId>${project.groupId}</groupId>
        <artifactId>DATA_MODULE_NAME</artifactId>
        <version>${project.version}</version>
    </dependency>
</dependencies>

当您构建最终 jar 时,源模块中的资源将被复制并使用getResource()

于 2021-10-06T21:58:08.887 回答