如何从Java模块排除Maven资源文件夹?解决模块包冲突问题
问题:Maven资源文件夹引发Java模块包冲突
我创建了javafx和commonfx两个Maven项目来复现错误,项目结构如下:

模块定义
commonfx模块
module commonfx { exports commonfx.calculator; }
javafx模块
module javafx { requires javafx.controls; requires javafx.graphics; requires javafx.fxml; requires commonfx; opens org.example to javafx.graphics, javafx.fxml; }
错误信息
两个项目都包含资源文件夹,虽然没有导出这些文件夹,但启动时持续报错:
Error occurred during initialization of boot layer java.lang.LayerInstantiationException: Package bundle in both module javafx and module commonfx
每次重启应用都会出现不同的错误,但核心都是提示两个模块存在同名资源文件夹对应的包:
Error occurred during initialization of boot layer java.lang.LayerInstantiationException: Package images in both module commonfx and module javafx Error occurred during initialization of boot layer java.lang.LayerInstantiationException: Package main.resources.images in both module commonfx and module javafx.
使用的技术栈
- Java 21
- JavaFX SDK 21
- Eclipse IDE for Enterprise Java and Web Developers 2024-03版本
- Maven 3.9.6
请问Maven资源文件夹是否被模块系统识别了?能不能从Java模块中排除Maven资源文件夹来解决这个冲突?
可复现异常的代码
commonfx项目
核心类代码
package commonfx.calculator; public class FxCalculator { public FxCalculator() { super(); } public Integer calculate() { return 2; } }
pom.xml配置
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>common.fx</groupId> <artifactId>commonfx</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <maven.compiler.source>21</maven.compiler.source> <maven.compiler.target>21</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <javafx.version>21</javafx.version> <javafx.maven.plugin.version>0.0.8</javafx.maven.plugin.version> </properties> <dependencies> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-controls</artifactId> <version>21.0.2</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-fxml</artifactId> <version>${javafx.version}</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-web</artifactId> <version>${javafx.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.openjfx</groupId> <artifactId>javafx-maven-plugin</artifactId> <version>${javafx.maven.plugin.version}</version> </plugin> </plugins> </build> </project>
javafx项目
核心类代码
package org.example; import commonfx.calculator.FxCalculator; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class Javafx extends Application { private FxCalculator calculator; @Override public void start(Stage stage) { String javaVersion = System.getProperty("java.version"); String javafxVersion = System.getProperty("javafx.version"); calculator = new FxCalculator(); Label l = new Label("Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + "." + " Number FX: " + calculator.calculate()); Scene scene = new Scene(new StackPane(l), 640, 480); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(); } }
pom.xml配置
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>javafx</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <maven.compiler.source>21</maven.compiler.source> <maven.compiler.target>21</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <javafx.version>21</javafx.version> <javafx.maven.plugin.version>0.0.8</javafx.maven.plugin.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>3.2.4</version> </dependency> <dependency> <groupId>net.rgielen</groupId> <artifactId>javafx-weaver-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-controls</artifactId> <version>21.0.2</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-fxml</artifactId> <version>${javafx.version}</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-web</artifactId> <version>${javafx.version}</version> </dependency> <dependency> <groupId>common.fx</groupId> <artifactId>commonfx</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.openjfx</groupId> <artifactId>javafx-maven-plugin</artifactId> <version>${javafx.maven.plugin.version}</version> <configuration> <mainClass>org.example.Javafx</mainClass> </configuration> </plugin> </plugins> </build> </project>
解决方案
问题根源
Java模块系统会将JAR中所有的目录都视为包,哪怕目录里只有资源文件。当两个模块存在同名的资源目录时,就会触发LayerInstantiationException——因为Java不允许不同模块包含同一个包。
Maven默认会把src/main/resources下的内容复制到JAR的根目录,所以如果两个项目的src/main/resources下有同名文件夹(比如images、bundle),打包后就会在各自模块的JAR中生成同名包,直接导致冲突。
解决方法
1. 为每个模块的资源设置独立的目录结构(推荐)
最直接且可靠的方式是给每个模块的资源文件夹加上模块专属的前缀,比如:
- commonfx项目:
src/main/resources/commonfx/images - javafx项目:
src/main/resources/org/example/images
这样打包后,资源会分别归属到commonfx.images和org.example.images包,完全避免冲突。
2. 通过Maven配置修改资源输出路径
如果不想调整目录结构,可以在pom.xml中配置maven-resources-plugin,将资源输出到模块专属的路径下:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.3.1</version> <configuration> <!-- 将资源输出到以模块专属路径命名的目录下 --> <outputDirectory>${project.build.outputDirectory}/common/fx</outputDirectory> </configuration> </plugin> </plugins> </build>
注意每个模块要配置不同的outputDirectory,确保资源包路径唯一。
3. 排除特定资源目录(不推荐)
如果某些资源确实不需要打包到模块中,可以在pom.xml中排除它们:
<build> <resources> <resource> <directory>src/main/resources</directory> <excludes> <exclude>images/**</exclude> <exclude>bundle/**</exclude> </excludes> </resource> </resources> </build>
但这种方式会丢失资源文件,只适用于确实不需要这些资源的场景。
额外提示
- Eclipse的模块系统检测可能比Maven打包更严格,即使本地开发时没报错,打包后也可能出现冲突,所以优先推荐调整资源目录结构。
- 确保两个模块的
module-info.java中没有意外声明或导出这些资源包——虽然你没手动导出,但模块系统会自动识别JAR中的所有包。
内容的提问来源于stack exchange,提问作者Billie
相关产品推荐
相关产品推荐

