1

我有以下代码:

fun main(args: Array<String>) {
    val urlForCSR: URL = ClassLoader.getSystemClassLoader().getResource("merchant.id")
    // also tried ClassLoader.getSystemResource("merchant.id")
    ...

从 intelliJ 运行时,以下内容可以正常工作并找到资源。但是当使用捆绑的 jar 运行时,它会给出一个NullPointerException.

  • 资源路径:/src/main/resources/merchant.id
  • 代码路径:/src/main/java/Route.kt

以下是 Maven 配置片段:

    ...
    <!-- Make this jar executable -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>RouteKt</mainClass> <!-- Class generated (for above main func - named Route.kt) -->
                    </manifest>
                </archive>
            </configuration>
        </plugin>

        <!-- Includes the runtime dependencies -->
        <plugin>
            <groupId>org.dstovall</groupId>
            <artifactId>onejar-maven-plugin</artifactId>
            <version>1.4.4</version>
            <executions>
                <execution>
                    <goals>
                        <goal>one-jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>

是否有任何其他战争来获取上述资源的 URL,这将与一个罐子或其他制作胖罐子的方式一起使用。

罐子内容:

jar tf target/Route-1.0-SNAPSHOT.jar
META-INF/
META-INF/MANIFEST.MF
merchant.id
RouteKt$main$1.class
RouteKt.class
META-INF/maven/
META-INF/maven/groupId/
META-INF/maven/groupId/TokenGenerator/
META-INF/maven/groupId/TokenGenerator/pom.xml
META-INF/maven/groupId/TokenGenerator/pom.properties

一罐内容:

META-INF/MANIFEST.MF
main/Route-1.0-SNAPSHOT.jar
lib/kotlin-stdlib-0.1-SNAPSHOT.jar
lib/kotlin-runtime-0.1-SNAPSHOT.jar
lib/spark-core-2.3.jar
lib/slf4j-api-1.7.12.jar
lib/slf4j-simple-1.7.12.jar
lib/jetty-server-9.3.2.v20150730.jar
...
4

1 回答 1

5

OneJar 将所有代码打包到一个 JAR 文件中,该文件还包含lib/目录中的其他 JAR 文件,或者作为对 JAR 外部其他目录中的引用(取决于您使用的 onejar 系统)。它使用自定义类加载器来完成这项工作。因此,它使您无法使用系统类加载器。

解决此问题的一种方法是使用与要加载的资源相同的 JAR 中的类,因此其类加载器可能已正确设置到资源的 JAR 或嵌套 JAR 或资源的纳尼亚魔法位置:

val stream = MyClass::class.java.getResourceAsStream("/merchant.id")

哪里MyClass是来自同一个 JAR 的类merchant.id,并且资源的路径必须是绝对的,并带有前导/

确保获取而不是可能对您不可用的资源 URL,因为它不是系统可以理解的 URL。例如,它可以为 JAR 中的 JAR 生成一个其他 Java 无法理解的 URL file:/path/to/jarfile/bot.jar!/config/file.txt(或者更糟!)。它可以工作,但我不确定它何时是 JAR 中的 JAR,其中包含文件。

次要选项:

val stream = Thread.currentThread().contextClassLoader.getResourceAsStream("/merchant.id")

检查您的资源名称:

在您的问题中,您说要读取资源merchant.id,然后显示 JAR 内容merchant.id.soft.applepaydev-v1.csr...如果您尝试加载此确切资源,请确保这些名称匹配。


onejar中的资源加载必须自定义,很丑。 在一个资源的链接中,该资源讨论了使用 onejar 加载资源

Java 支持查找和打开资源的方式有多种:

  • URL findResource(String resource):返回一个资源,如果没有找到则返回null。
  • 枚举 findResources(String resource):返回与给定字符串匹配的资源 URL 的枚举
  • URL.openConnection():通过其 URL 打开到资源的连接。

One-Jar 在 One-Jar 文件的上下文中支持所有这些机制,该文件可能包含具有重复资源的 Jar 文件。

这个问题是从这些其他 Stack Overflow 帖子中引用的,因此这几乎是一个重复的问题:

谷歌搜索会发现更多资源。

于 2016-01-06T04:57:19.513 回答