Maven多模块项目:解决子模块自引用错误并排除根POM依赖
问题描述
我有一个Maven多模块项目,根pom.xml中声明了包括resources子模块在内的依赖。resources子模块仅用于存放各子模块的公共资源,不需要任何依赖。现在出现了子模块自引用错误,错误信息如下:
The project com.github.alopatin.kafka_learning.java:resources:1.0 (D:\Wokrspace\kafka-learing\java\resources\pom.xml) has 1 error
[ERROR]
'dependencies.dependency.[com.github.alopatin.kafka_learning.java:resources:1.0]' for com.github.alopatin.kafka_learning.java:resources:1.0 is referencing itself. @ com.github.alopatin.kafka_learning.java:java:1.0, D:\Wokrspace\kafka-learing\java\pom.xml, line 36, column 21
根POM代码如下:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.github.alopatin.kafka_learning.java</groupId> <artifactId>java</artifactId> <version>1.0</version> <modules> <module>resources</module> <module>producer-simple</module> <module>producer-json</module> </modules> <properties> <maven.compiler.source>23</maven.compiler.source> <maven.compiler.target>23</maven.compiler.target> </properties> <packaging>pom</packaging> <dependencies> <dependency> <groupId>com.github.alopatin.kafka_learning.java</groupId> <artifactId>resources</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>com.typesafe</groupId> <artifactId>config</artifactId> <version>1.4.3</version> </dependency> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> <version>3.8.1</version> </dependency> </dependencies> <build> ... </build> </project>
问题原因
Maven中,根POM的<dependencies>块内的依赖会被所有子模块自动继承。你的根POM里声明了resources子模块的依赖,而resources子模块本身继承根POM,这就导致它自己引入了自己的依赖,触发自引用错误。
解决方案
方法1:使用<dependencyManagement>统一管理依赖(推荐)
把根POM中的依赖移到<dependencyManagement>块,这个块仅负责声明依赖版本,不会让子模块自动继承,需要依赖的子模块再单独引入。
修改后的根POM:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.github.alopatin.kafka_learning.java</groupId> <artifactId>java</artifactId> <version>1.0</version> <modules> <module>resources</module> <module>producer-simple</module> <module>producer-json</module> </modules> <properties> <maven.compiler.source>23</maven.compiler.source> <maven.compiler.target>23</maven.compiler.target> </properties> <packaging>pom</packaging> <!-- 用dependencyManagement统一管理依赖版本,子模块不会自动继承 --> <dependencyManagement> <dependencies> <dependency> <groupId>com.github.alopatin.kafka_learning.java</groupId> <artifactId>resources</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>com.typesafe</groupId> <artifactId>config</artifactId> <version>1.4.3</version> </dependency> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> <version>3.8.1</version> </dependency> </dependencies> </dependencyManagement> <build> ... </build> </project>
然后在需要依赖的子模块(比如producer-simple、producer-json)的pom.xml中引入所需依赖:
<dependencies> <!-- 引入resources模块,无需写版本,会继承根POM的声明 --> <dependency> <groupId>com.github.alopatin.kafka_learning.java</groupId> <artifactId>resources</artifactId> </dependency> <!-- 引入其他需要的依赖 --> <dependency> <groupId>com.typesafe</groupId> <artifactId>config</artifactId> </dependency> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> </dependency> </dependencies>
resources子模块的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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>com.github.alopatin.kafka_learning.java</groupId> <artifactId>java</artifactId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>resources</artifactId> <!-- 纯资源模块设置为jar打包即可 --> <packaging>jar</packaging> </project>
方法2:在resources子模块中排除自引用依赖
如果不想改动根POM的结构,可以在resources子模块的pom.xml中排除自身的依赖:
<dependencies> <dependency> <groupId>com.github.alopatin.kafka_learning.java</groupId> <artifactId>java</artifactId> <version>1.0</version> <type>pom</type> <exclusions> <exclusion> <groupId>com.github.alopatin.kafka_learning.java</groupId> <artifactId>resources</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
不过这种方法不够优雅,更推荐使用第一种方案。
内容的提问来源于stack exchange,提问作者Alexander Lopatin

