【问题标题】:Java Library: load file from resourcesJava 库:从资源中加载文件
【发布时间】:2022-03-06 00:01:29
【问题描述】:

我正在开发一个将在我们公司内部使用的 Java 库。它为 Aerospike 提供了一个包装器。当用户调用工厂方法时,库应该从其资源中读取文件。

public static IAerospikeClient newTypedClient(IAerospikeClient client) {
    LOG.info("Trying to load aerospike schema yml");

    URL resource = AerospikeTypedClientFactory.class.getClassLoader().getResource("schema.yml");
    if (resource == null) {
        throw new IllegalArgumentException("File 'schema.yml' is not found");
    }

    byte[] bytes = Files.readAllBytes(Paths.get(resource.toURI()));
    return new TypedAerospikeClient(client, new String(bytes));
}

然后我尝试将此库添加为依赖项并调用newTypedClient 方法,我收到此错误。

Caused by: java.nio.file.FileSystemNotFoundException
    at com.sun.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:171)
    at com.sun.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:157)
    at java.nio.file.Paths.get(Paths.java:143)
    at com.example.AerospikeTypedClientFactory.newTypedClient(AerospikeTypedClientFactory.java:30)

有没有办法克服这个错误?我想我可以将schema.yml 文件添加到图书馆使用者的resources 文件夹中。但我绝对不想进入这个。因为目的是摆脱配置并将它们放在单个工件中。

编辑 1

对于那些参考How should I use getResource() in Java?问题的人。我知道getResource 从类路径中读取。我的问题是我怎样才能得到这份工作?也许,我可以用其他东西替换 getResource/getResourceAsStream 用法。这个想法是 schema.yml 必须打包在库 .jar 存档中。

编辑 2

这是一步一步的问题。

  1. 所描述的代码放在lib 模块中。
  2. lib 打包到 jar 并发布到 Artifactory。
  3. service 依赖于 lib
  4. servicelib 调用 newTypedClient 方法。
  5. FileSystemNotFoundException 加注。

所以,我需要 lib 从包装到的 jar 中读取 schema.yml。可能吗?这是描述该过程的图表。

【问题讨论】:

  • 这能回答你的问题吗? How should I use getResource() in Java?
  • @pringi 不,它没有。我用解释更新了问题
  • 所以,如果我正确理解了您的问题...一旦您构建了 JAR 文件,如果您使用存档工具(例如 7-Zip)打开它,那么您将找不到 schema.yml在场吗?
  • @pringi 不,存在不同类型的问题。假设有一个servicelib 上面的代码。我将lib 作为build.gradleservice 的依赖项。当我在service 代码中调用newTypedClient 方法时,我得到了所描述的异常。所以,我希望lib 从其resources 文件夹中读取schema.yml。当我单独测试lib 时,它确实有效。但是当我将lib 包含为依赖项时,它会停止工作。
  • @pringi 我为这个问题再举一个例子。

标签: java gradle shared-libraries classpath java-resources


【解决方案1】:

对于那些感兴趣的人,我编写了一个自定义 Gradle 任务,它生成一个带有静态 String 字段的类。该字段值等于实际文件内容。该任务在compileJava 之前运行。 对于一代本身,我使用JavaPoet 库。 这是一个例子。

task generateSchemaClass {
    def className = "Schema_"
    def directoryPath = "src/main/java/com/example/generated"
    def filePath = directoryPath + className + ".java"
    doFirst {
        TypeSpec typeSpec = TypeSpec.classBuilder("Schema_")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(
                        AnnotationSpec.builder(SuppressWarnings.class)
                                .addMember("value", '$S', "all")
                                .build()
                )
                .addField(
                        FieldSpec.builder(String.class, "CONTENT", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
                                .initializer('$S', file('src/main/resources/schema.yml').text)
                                .build()
                )
                .build()
        JavaFile javaFile = JavaFile.builder("com.example.generated", typeSpec).build()
        file(directoryPath).mkdirs()

        def output = file(filePath)
        output.createNewFile()
        output.text = javaFile.toString()
    }
}

compileJava.dependsOn(generateSchemaClass)

【讨论】:

    猜你喜欢
    • 2010-11-13
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多