java java-9 jigsaw

java - Acceso a archivos de recursos desde módulos externos



java-9 jigsaw (2)

Hasta ahora, hasta que Java no esté modularizado, simplemente debe colocar un archivo en src/main/java/resources para asegurarse de que esté en classpath y luego cargarlo con

file = getClass().getClassLoader().getResourceAsStream("myfilename");

desde prácticamente cualquier parte del classpath.

Ahora con módulos, la trama se complica.

La configuración de mi proyecto es la siguiente:

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

El archivo de configuración se coloca dentro de src/main/resources/config.yml .

El proyecto se ejecuta con

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

Como la clase principal no reside en mi propio proyecto, sino en un módulo de marco externo, no puede ver config.yml . Ahora la pregunta es, ¿hay alguna manera de poner de alguna manera mi archivo de configuración en el módulo o abrirlo? ¿Tengo que cambiar la forma en que el archivo se carga en el marco ascendente?

Traté de usar "exportaciones" o "abre" en la información del módulo, pero quiere tener un nombre de paquete, no un nombre de carpeta.

¿Cómo lograr esto de la mejor manera práctica para que funcione como en Java 8 y con la menor cantidad de cambios posible?


Mientras usa el comando java para iniciar una aplicación de la siguiente manera: -

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

  • está especificando el modulepath usando la opción -p alternativa para --module-path que buscaría en target / classes y target / dependency para sus módulos.

  • Además, el uso de -m alternativo para --module especifica el módulo inicial para resolver con el nombre framework.core y construye el gráfico del módulo con la clase principal para ejecutar explícitamente como com.framework.Main .

Ahora, el problema aquí parece ser que el módulo framework.core no requires o lee el módulo playground.api debido a que el gráfico del módulo no incluye el módulo deseado que consiste en el recurso real config.yml .

Según lo sugerido por @Alan , una buena manera de enumerar la salida de resolución del módulo durante el inicio es utilizar la opción --show-module-resolution .

Intenté ingenuamente abrir src / main / resources, no compila ofc

Dado que el recurso en su módulo está en el nivel raíz , por lo tanto, no está encapsulado y no necesita abrirse ni exportarse a ningún otro módulo.

En su caso, solo necesita asegurarse de que el módulo playground.api termine en el gráfico del módulo y luego el recurso sea accesible para la aplicación. Para especificar los módulos raíz a resolver además del módulo inicial, puede utilizar la opción --add-modules .

Por lo tanto, la solución general para trabajar para usted junto con alguna depuración será:

java --module-path target/classes:target/dependency --module framework.core/com.framework.Main --add-modules playground.api --show-module-resolution


// 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)

Vea un ejemplo de trabajo a continuación.

Dado:

. ├── 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 podría ser

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); } }

Y lanzarías con

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

Para clonar este ejemplo: git clone https://github.com/j4n0/SO-46861589.git