java - 从外部模块访问资源文件

标签 java java-9 java-platform-module-system

到目前为止,在非模块化 java 之前,您只需将文件放在 src/main/java/resources 中,确保它在类路径中,然后使用

加载它
file = getClass().getClassLoader().getResourceAsStream("myfilename"); 

几乎来自类路径中的任何地方。

现在有了模块,情节变得更复杂了。

我的项目设置如下:

module playground.api {
    requires java.base;
    requires java.logging;
    requires framework.core;
}

配置文件放在 src/main/resources/config.yml 中。

项目运行

java -p target/classes:target/dependency -m framework.core/com.framework.Main

由于主类不在我自己的项目中,而是在一个外部框架模块中,所以看不到config.yml。现在的问题是,有没有办法以某种方式将我的配置文件放入模块或打开它?我是否必须更改上游框架加载文件的方式?

我尝试在模块信息中使用“exports”或“opens”,但它想要一个包名称,而不是文件夹名称。

如何以最实用的方式实现这一目标,使其像在 Java 8 中一样工作,并尽可能少地进行更改?

最佳答案

// to scan the module path
ClassLoader.getSystemResources(resourceName)

// if you know a class where the resource is
Class.forName(className).getResourceAsStream(resourceName)

// if you know the module containing the resource
ModuleLayer.boot().findModule(moduleName).getResourceAsStream(resourceName)

请参阅下面的工作示例。


给定:

.
├── FrameworkCore
│   └── src
│       └── FrameworkCore
│           ├── com
│           │   └── framework
│           │       └── Main.java
│           └── module-info.java
└── PlaygroundApi
    └── src
        └── PlaygroundApi
            ├── com
            │  └── playground
            │      └── api
            │          └── App.java
            ├── config.yml
            └── module-info.java

Main.java 可以是

package com.framework;

import java.io.*;
import java.net.URL;
import java.util.Optional;
import java.util.stream.Collectors;

public class Main {
    public static void main( String[] args )
    {
        // load from anywhere in the modulepath
        try {
            URL url = ClassLoader.getSystemResources("config.yml").nextElement();
            InputStream is = url.openStream();
            Main.read(is);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // load from the the module where a given class is
        try {
            InputStream is = Class.forName("com.playground.api.App").getResourceAsStream("/config.yml");
            Main.read(is);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

        // load from a specific module
        Optional<Module> specificModule = ModuleLayer.boot().findModule("PlaygroundApi");
        specificModule.ifPresent(module -> {
            try {
                InputStream is = module.getResourceAsStream("config.yml");
                Main.read(is);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    private static void read(InputStream is) {
        String s = new BufferedReader(new InputStreamReader(is)).lines().collect(Collectors.joining("\n"));
        System.out.println("config.yml: " + s);
    }
}

然后您将启动

java --module-path ./FrameworkCore/target/classes:./PlaygroundApi/target/classes \
     --add-modules FrameworkCore,PlaygroundApi \
       com.framework.Main

要克隆此示例:git clone https://github.com/j4n0/SO-46861589.git

关于java - 从外部模块访问资源文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46861589/

相关文章:

java - 什么以及如何将 Java Swing 概念与云相关?

java - 如何使用正则表达式在同一行捕获可变数量的模式?

java - RestEasy JAX-RS ApplicationPath 返回 404

java - 在 JShell 中将变量转换为其原始形式

Java 9 : jigsaw and hibernate 5. 2.12 不工作

java - 如何从 Java 9 模块导出所有包?

java - Intellij Spring Initializr 不可用

java - 在 Java 9 的接口(interface)中使用抽象类有什么好的理由吗?

JavaFX:更新到 Java 9 后出现奇怪的 ClassNotFoundException

maven - Jigsaw 项目与 Maven