在kotlin func中使用资源 – 不能用fat jar(一个jar)

我有以下一段代码:

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或其他方式来制作一个胖罐子。

罐子内容:

 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 ... 

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

解决这个问题的方法之一是使用来自相同JAR的类作为要加载的资源,因此它的类加载器可能正确地安装到JAR中,或者在您的资源的Narnia中嵌套JAR或魔术位置:

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

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

确保获取流,而不是可能无法使用的资源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但然后显示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文件。

这个问题是从这些其他堆栈溢出帖子引用的,因此这几乎是一个重复的问题:

  • 通过sbt打包的one-jar中的类路径资源
  • 如何获取Java JAR文件中资源的路径
  • 如何在使用OneJar时获取资源目录的URL?
  • Onejar和资源加载

谷歌搜索变成了更多的资源。