Maven添加system scope依赖后子项目无法获取公共库其他依赖的问题
Maven System Scope依赖导致公共库依赖传递失效的问题与解决
问题描述
我维护一个被多项目依赖的公共库,在其pom.xml中添加了一个system scope的本地Jar依赖(gnu.io:rxtx:2.2pre2,路径为${project.basedir}/lib/RXTXcomm.jar)后,依赖该公共库的子项目无法获取公共库的其他正常依赖;移除这个system scope依赖后,子项目又能正常获取所有依赖。
公共库的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"> <modelVersion>4.0.0</modelVersion> <groupId>com.conceptualsystems</groupId> <artifactId>common</artifactId> <version>3.3</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.5.0-b01</version> </dependency> <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --> <!-- <dependency>--> <!-- <groupId>org.junit.jupiter</groupId>--> <!-- <artifactId>junit-jupiter</artifactId>--> <!-- <version>5.9.3</version>--> <!-- <scope>test</scope>--> <!-- </dependency>--> <dependency> <groupId>org.ini4j</groupId> <artifactId>ini4j</artifactId> <version>0.5.4</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>2.0.6</version> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20180813</version> </dependency> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.19</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>html2pdf</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.5.0-b01</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.1.1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.1.1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.1.1</version> </dependency> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.8.0</version> </dependency> <dependency> <groupId>gnu.io</groupId> <artifactId>rxtx</artifactId> <version>2.2pre2</version> <scope>system</scope> <systemPath>${project.basedir}/lib/RXTXcomm.jar</systemPath> </dependency> </dependencies> </project>
原因分析
- System Scope的本质限制:Maven的
systemscope依赖是为本地特定环境设计的,它不会参与依赖传递,而且Maven默认认为这类依赖无法被其他项目正常获取。 - 依赖传递抑制:当公共库中存在
systemscope依赖时,Maven在将公共库安装到本地/远程仓库时,会生成一个不包含完整依赖传递信息的POM文件。依赖该公共库的子项目在解析依赖时,会因为这个不完整的POM,无法获取公共库原本的正常依赖。
解决方案
方案一:将本地Jar安装到Maven仓库(推荐)
这是最规范的做法,把本地的RXTXcomm.jar安装到本地Maven仓库,之后就可以像普通依赖一样使用,不会影响依赖传递:
执行以下命令(在公共库根目录下):
mvn install:install-file -Dfile=lib/RXTXcomm.jar -DgroupId=gnu.io -DartifactId=rxtx -Dversion=2.2pre2 -Dpackaging=jar
然后修改公共库的pom.xml,把原来的system依赖改成普通依赖:
<dependency> <groupId>gnu.io</groupId> <artifactId>rxtx</artifactId> <version>2.2pre2</version> </dependency>
重新执行mvn clean install,子项目就能正常获取所有依赖。
方案二:构建时自动安装本地Jar(适合团队协作)
如果不想手动执行安装命令,可以在公共库的pom.xml中添加maven-install-plugin,在构建阶段自动安装本地Jar:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-install-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>install-rxtx</id> <phase>install</phase> <goals> <goal>install-file</goal> </goals> <configuration> <file>${project.basedir}/lib/RXTXcomm.jar</file> <groupId>gnu.io</groupId> <artifactId>rxtx</artifactId> <version>2.2pre2</version> <packaging>jar</packaging> </configuration> </execution> </executions> </plugin> </plugins> </build>
同样把原来的system依赖改成普通依赖,这样每次执行mvn install时,会自动把本地Jar安装到仓库,不影响依赖传递。
方案三:使用Optional标记(不推荐)
如果必须保留system scope,需要给该依赖加上<optional>true</optional>,同时在每个子项目中也添加相同的system依赖:
公共库中的依赖配置:
<dependency> <groupId>gnu.io</groupId> <artifactId>rxtx</artifactId> <version>2.2pre2</version> <scope>system</scope> <systemPath>${project.basedir}/lib/RXTXcomm.jar</systemPath> <optional>true</optional> </dependency>
但这种方式需要每个子项目都维护相同的本地Jar路径,扩展性差,不推荐在多项目依赖场景下使用。
内容的提问来源于stack exchange,提问作者moonlightcheese
相关产品推荐
相关产品推荐

