在kotlin函数中使用资源 - 不适用于胖罐(一个罐子)

时间:2016-01-06 04:15:14

标签: kotlin onejar

我有以下代码:

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内容:

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

1 个答案:

答案 0 :(得分:5)

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

打败这个的一种方法是使用与要加载的资源相同的JAR中的类,因此它的类加载器可能正确地设置到JAR或嵌套的JAR或魔术位置在纳尼亚你的资源:

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

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

请务必获取,而不是可能无法使用的资源网址,因为它不是系统可理解的网址。它可以在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

  

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

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

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

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

谷歌搜索会提供更多资源。