Maven多模块项目编译错误不终止,如何阻止组装模块生成Zip?
我手头有个包含proj-a、proj-b、proj-c等子模块的Maven多模块项目,其中专门加了一个assembler模块,靠maven-assembly-plugin把所有子模块生成的Jar打包成Zip包。但最近发现个坑:哪怕某个子模块编译出错,父POM的构建居然不会终止,assembler模块照样生成Zip包——这就导致打包出来的文件可能缺了某个子模块的Jar,完全不符合预期。想问问怎么才能做到:只要有子模块编译失败,就直接停止整个构建,不让assembler生成错误的Zip?
下面是我的项目配置:
父POM配置
<project 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.my.projects</groupId> <artifactId>packer</artifactId> <version>1.0.0</version> <packaging>pom</packaging> <modules> <module>../../com.proj-a</module> <module>../../com.proj-b</module> <module>../../com.proj-c</module> ........... <!-- assembling all jars --> <module>./assembler</module> </modules> </project>
assembler模块POM配置
<project 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.my.projects</groupId> <artifactId>assembler</artifactId> <version>1.0.0</version> <packaging>pom</packaging> <dependencies> <dependency> <groupId>com.my.projects</groupId> <artifactId>com.proj-a</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>com.my.projects</groupId> <artifactId>com.proj-b</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>com.my.projects</groupId> <artifactId>com.proj-c</artifactId> <version>1.0.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <executions> <execution> <id>make-bundles</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <finalName>release-all-for-test</finalName> <appendAssemblyId>false</appendAssemblyId> <descriptors> <descriptor>/src/resources/assembly-descriptor.xml</descriptor> </descriptors> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
assembly-descriptor.xml配置
<assembly xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd"> <id>dist-assembly</id> <formats> <format>zip</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <dependencySets> <dependencySet> <useTransitiveDependencies>false</useTransitiveDependencies> <outputDirectory>/out-put/WEB-INF/lib</outputDirectory> <useProjectArtifact>false</useProjectArtifact> <unpack>false</unpack> </dependencySet> </dependencySets> </assembly>
我之前也遇到过类似的问题,Maven默认会“顽强”地继续构建其他模块,哪怕某个子模块已经失败了。这里给你几个可行的解决方法,按推荐程度排序:
方法一:启用Maven快速失败模式(最简洁可靠)
Maven从3.3.1版本开始支持全局的快速失败配置,只要在父POM的<properties>里加一行配置,就能让构建在第一个失败的模块处立刻终止——这样assembler模块根本不会被执行,自然不会生成错误的Zip包。
修改父POM,添加如下配置:
<properties> <!-- 开启快速失败:只要有一个模块构建失败,整个构建立刻停止 --> <maven.build.failFast>true</maven.build.failFast> </properties>
这个方法的好处是一劳永逸,不用修改assembler模块的任何配置,所有子模块的失败都会直接终止构建。
方法二:给assembler模块添加前置依赖检查
如果你不想全局开启快速失败,只想针对assembler模块做限制,可以用maven-enforcer-plugin在assembler打包前检查所有依赖的子模块Jar是否存在——如果子模块编译失败,对应的Jar不会被安装到本地仓库,这个检查就会失败,从而阻止assembly插件执行。
修改assembler模块的POM,在<build><plugins>中添加enforcer插件:
<!-- 先添加依赖检查插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>check-dependency-jars</id> <phase>prepare-package</phase> <!-- 在打包前执行检查 --> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <requireFilesExist> <files> <!-- 检查每个子模块的Jar是否存在于本地仓库 --> <file>${settings.localRepository}/com/my/projects/com.proj-a/1.0.0/com.proj-a-1.0.0.jar</file> <file>${settings.localRepository}/com/my/projects/com.proj-b/1.0.0/com.proj-b-1.0.0.jar</file> <file>${settings.localRepository}/com/my/projects/com.proj-c/1.0.0/com.proj-c-1.0.0.jar</file> </files> <message>依赖的子模块Jar不存在,大概率是子模块编译失败了!</message> </requireFilesExist> </rules> </configuration> </execution> </executions> </plugin> <!-- 原来的assembly插件保持不变 --> <plugin> <artifactId>maven-assembly-plugin</artifactId> <executions> <execution> <id>make-bundles</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <finalName>release-all-for-test</finalName> <appendAssemblyId>false</appendAssemblyId> <descriptors> <descriptor>/src/resources/assembly-descriptor.xml</descriptor> </descriptors> </configuration> </execution> </executions> </plugin>
方法三:调整assembler模块的打包类型
你现在的assembler模块打包类型是pom,Maven对pom类型的模块不会严格检查依赖模块的构建状态。把它改成jar类型(哪怕模块里没有源代码),Maven就会强制要求所有依赖的子模块必须构建成功后,才会处理assembler的打包阶段。
步骤1:修改assembler模块的打包类型
<packaging>jar</packaging>
步骤2:跳过空Jar的生成(可选)
如果不想让assembler生成一个空的Jar包,可以添加maven-jar-plugin跳过默认的Jar生成:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>default-jar</id> <phase>none</phase> <!-- 跳过默认的Jar生成阶段 --> </execution> </executions> </plugin>
内容的提问来源于stack exchange,提问作者kurious

