在 kotlin func 中使用资源 - 不适用于 fat jar(一个 jar)

Using resource in kotlin func - does not work with fat jar (one jar)

我有如下一段代码:

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

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

以下是 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>

对于上述资源,是否有任何其他 war 可以获得 URL,可以使用一个罐子或其他制作胖罐子的方法。

罐子内容:

jar tf target/Route-1.0-SNAPSHOT.jar
META-INF/
META-INF/MANIFEST.MF
merchant.id
RouteKt$main.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
...

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

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

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

其中 MyClass 是来自与 merchant.id 相同 JAR 的 class,资源路径必须是绝对路径,前导 /

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

次要选项:

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

检查您的资源名称:

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


onejar 中的资源加载必须自定义,这很难看。 In a link to one resource that talks about resource loading with onejar:

There are a number of ways that Java supports finding and opening resources:

  • URL findResource(String resource): returns a resource, or null if not found.
  • Enumeration findResources(String resource): returns an enumeration of resource URL's which match the given string
  • URL.openConnection(): opens a connection to a resource by its URL.

One-Jar supports all of these mechanisms within the context of a One-Jar file, which may contain Jar files that have duplicate resources.

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

  • Classpath resources inside one-jar packaged via sbt
  • How to get a path to a resource in a Java JAR file
  • How to get an URL for a resource directory when using OneJar?
  • Onejar and resource loading

谷歌搜索找到更多资源。