Maven——Maven开发经验总结(1)
摘要
本文总结了 Maven 开发中的多个关键经验,包括如何根据版本号决定推送到 releases 或 snapshots 仓库,如何在构建过程中跳过测试,父项目如何控制子项目依赖版本,父项目依赖是否能传递到子项目,如何跳过 Maven deploy 中的某个 module,以及 Maven package 时如何跳过测试等,为 Maven 开发提供了实用指南。
1. Maven在运行部署的时候是如何确定推送到Releases还是Snapshots仓库
在 Maven 中,部署到 releases
或 snapshots
仓库的决定是通过版本号来判断的。具体规则如下:
- 版本号规则:
-
- Release 版本:如果版本号不包含
-SNAPSHOT
后缀,Maven 会认为这是一个稳定的发布版本,并会推送到releases
仓库。例如:1.0.0
。 - Snapshot 版本:如果版本号包含
-SNAPSHOT
后缀,Maven 会认为这是一个开发版本,并会推送到snapshots
仓库。例如:1.0.0-SNAPSHOT
。
- Release 版本:如果版本号不包含
- Maven 配置文件(
pom.xml
): 在你的项目的pom.xml
文件中,指定仓库的 URL 和仓库的 ID。通常,在<distributionManagement>
部分,Maven 会配置releases
和snapshots
仓库的地址。例如:
<distributionManagement>
<repository>
<id>releases</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
在这里,Maven 会根据你的版本号(是否包含 -SNAPSHOT
后缀)决定将构件部署到哪个仓库。
- 部署过程:
-
- 当你执行
mvn deploy
时,Maven 会根据pom.xml
中的版本号以及配置文件中的仓库信息判断将构件推送到哪个仓库。 - 对于
SNAPSHOT
版本,Maven 会推送到snapshots
仓库,并且通常会带有时间戳,允许多个相同版本的构件在同一时间存在。 - 对于
release
版本,Maven 会推送到releases
仓库,并且这个版本通常是稳定的,不会再更新。
- 当你执行
- 推送行为:
-
- 对于
SNAPSHOT
版本,Maven 会允许在推送时覆盖同一版本号的构件(如:同一版本的1.0.0-SNAPSHOT
可以被不同的构建替换),这使得开发过程中可以频繁更新。
- 对于
- 对于
release
版本,推送到releases
仓库时,版本号必须是唯一的,不允许覆盖已发布的版本。
总结来说,版本号的后缀决定了推送目标仓库:
-SNAPSHOT
推送到snapshots
仓库。- 不含
-SNAPSHOT
的版本推送到releases
仓库。
2. Maven在构建过程中跳过测试
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- 跳过测试 -->
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
2.1. Maven Surefire Plugin 的作用
- Maven Surefire Plugin 是 Maven 的核心插件之一,用于执行单元测试。
- 默认情况下,Maven 在构建项目时会自动运行
src/test/java
目录下的测试类。 - 通过配置
<skip>true</skip>
,可以跳过测试阶段,从而加快构建速度。
2.2. 实际应用场景
- 加快构建速度: 在开发过程中,如果不需要运行测试,可以通过跳过测试来加快构建速度。
- 跳过失败的测试: 如果某些测试暂时失败,但需要继续构建项目,可以通过跳过测试来避免构建失败。
- 配置统一管理: 在大型项目中,可以通过
<pluginManagement>
集中管理插件配置,确保所有子项目使用相同的插件行为。
2.3. 注意事项
- 如果需要强制跳过测试,可以在命令行中直接使用
-DskipTests
参数,例如:
mvn clean install -DskipTests
- 如果只是跳过测试的编译,可以使用
-Dmaven.test.skip=true
参数,例如:
mvn clean install -Dmaven.test.skip=true
3. Maven 项目中父项目pom 控制子项目pom的依赖版本吗?
是的,在 Maven 项目中,父 pom.xml
可以控制 子模块 (sub-modules
) 的依赖版本,主要有两种方式:
3.1. 使用<dependencyManagement>
统一管理版本
推荐做法:在 父 pom.xml
里使用 <dependencyManagement>
只定义依赖版本,子模块在引入时不需要指定版本。
3.1.1. 父项目 pom.xml
<project>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>sub-module-a</module>
<module>sub-module-b</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.5</version> <!-- 统一管理版本 -->
</dependency>
</dependencies>
</dependencyManagement>
</project>
3.1.2. 子项目 pom.xml
(无需指定版本)
<project>
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>sub-module-a</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
3.1.3. ✅ 优势
- 子模块无需指定版本,版本由父
pom.xml
控制,保证一致性。 - 便于升级依赖,只需修改父
pom.xml
中的版本号。
3.2. 直接在 <dependencies>
中定义(不推荐)
如果在 父 pom.xml
里直接写 <dependencies>
,那么子模块会继承这些依赖,但子模块如果有自己的版本,可能会发生冲突。
3.2.1. 父项目 pom.xml
<project>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.5</version> <!-- 子模块会自动继承 -->
</dependency>
</dependencies>
</project>
3.2.2. 子项目 pom.xml
e<project>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
3.2.3. ⚠️ 缺点
- 子模块无法单独管理依赖版本,可能会与其他依赖冲突。
- 如果子模块也指定了版本,可能导致版本不一致(依赖冲突)。
3.3. Maven父子项目依赖管理总结
方式 | 方式 1(✅ 推荐) | 方式 2(⚠️ 不推荐) |
子模块是否需要指定版本 | 不需要,父 POM 控制 | 需要,如果不指定可能继承 |
子模块能否覆盖版本 | 可以,但默认使用父 POM 版本 | 可以,但可能会版本冲突 |
适合多模块项目 | 是,能确保版本统一 | 否,易发生版本冲突 |
最佳实践
- 在父
pom.xml
里使用<dependencyManagement>
统一管理版本。 - 子模块只声明依赖,不要指定版本,避免版本混乱。
这种方式适用于 Spring Boot、MyBatis、Dubbo 等大部分多模块 Maven 项目,能提高维护性和稳定性。🚀
4. 父项目Maven依赖是否可以传递到子项目
一个项目引用了nacos的依赖,这个项目中依赖jar 也使用naocs的配置,请问这个的jar 在打包的时候是否需要使用ncos依赖 进行package 。
在你的项目中,如果引用了 Nacos 作为依赖,并且其他 jar
包也使用了 Nacos 配置,通常来说,这些 jar
包在打包时是否需要包含 Nacos 依赖,取决于你对项目的构建方式和依赖管理的配置。
4.1. 依赖传递(Transitive Dependency):
如果你在主项目中引用了 Nacos 的依赖,并且这个主项目的 jar
包会包含并传递 Nacos 依赖给其他模块,那么其他 jar
包在打包时通常 不需要再单独引用 Nacos,主项目中的 Nacos 依赖会被自动引入。这种情况通常适用于基于 Maven 或 Gradle 构建的项目,依赖会在构建时被传递。
例如,在 Maven 项目中,Nacos 的依赖应该已经在父项目的 pom.xml
中声明:
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>2.x.x</version>
</dependency>
4.2. 独立打包(Standalone Packaging)
如果你要将某些 jar
包独立打包为单独的应用,且这些应用需要独立引用 Nacos 依赖(例如,一个 jar
作为微服务应用单独运行),那么这些 jar
在打包时可能需要单独包含 Nacos 依赖。你可以通过使用 shade
插件(Maven)或其他类似的工具,将所有依赖都打包进最终的 jar
包中。
示例: Maven 中使用 maven-shade-plugin
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.x.x</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactSet>
<excludes>
<exclude>com.alibaba.nacos:nacos-client</exclude> <!-- 排除某些依赖 -->
</excludes>
</artifactSet>
</configuration>
</plugin>
4.3. 使用 provided
作用域
如果 Nacos 只在运行时需要(例如在容器或框架中自动注入),你可以将 Nacos 依赖的作用域设置为 provided
。这样,Nacos 不会被打包进最终的 jar
中,而是在运行时由外部环境提供。
例如,在 Maven 中设置 Nacos 依赖为 provided
:
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>2.x.x</version>
<scope>provided</scope>
</dependency>
4.4. 依赖的 jar
包直接引用 Nacos
如果某些 jar
包本身直接引用了 Nacos,那么它们在编译时会自动将 Nacos 依赖引入。当这些 jar
被打包时,它们会将这些依赖一起打包。如果你使用 fat jar
或 uber jar
方式打包,这些依赖也会被包括进去。
4.5. 依赖传递总结
- 如果你依赖的
jar
包已经在主项目中引用了 Nacos,且你使用的是 Maven 或 Gradle 等构建工具,通常 不需要再次单独引入 Nacos。 - 如果你希望 独立打包并包含 Nacos,可以使用
shade
插件或者类似的工具。 - 若 Nacos 仅用于运行时而不需要打包到
jar
中,可以使用provided
作用域。
根据项目的具体需求和构建方式,你可以选择适合的方式来管理 Nacos 依赖。
5. Maven deploy跳过某个module解决办法
在使用 Maven 时,如果你希望跳过某个模块的 deploy
操作(即不将某个模块部署到远程仓库),可以通过以下几种方法来实现:
5.1. 方法 1:使用 -pl
参数(指定要部署的模块)
你可以使用 -pl
参数来指定需要部署的模块列表,跳过不需要部署的模块。比如,假设你有一个多模块项目,其中有一个模块你不想部署,可以通过指定其它模块来跳过这个模块的部署。
mvn deploy -pl !module-to-skip
-pl
:指定要构建或部署的模块。!module-to-skip
:通过!
语法排除module-to-skip
模块。
5.2. 方法 2:在 pom.xml
中使用 profiles
配置
你可以在 pom.xml
文件中定义一个专门的 Maven profile
,并在该 profile 中排除某些模块的构建或部署。通过在构建时激活该 profile
来跳过某个模块。
示例:在父 pom.xml
中配置一个 deploy-skip
profile,指定不部署某个模块:
<profiles>
<profile>
<id>deploy-skip</id>
<modules>
<module>module1</module>
<module>module2</module>
<!-- 排除 module-to-skip -->
</modules>
</profile>
</profiles>
然后通过 -P
参数激活该 profile:
mvn deploy -Pdeploy-skip
这种方法适用于你有多个环境或配置,并且希望在不同的构建配置下部署不同的模块。
5.3. 方法 3:跳过特定的模块构建和部署
如果你希望完全跳过某个模块的构建或部署,可以通过设置 skip
配置,跳过该模块的构建或 deploy
生命周期。例如,如果某个模块的构建时间较长,或因其他原因不需要部署,可以在其 pom.xml
中添加以下配置来跳过部署:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
5.4. 方法 4:使用 maven-skip-plugin
有时候,如果你只是想简单地跳过某个模块的构建或 deploy
,你可以使用 maven-skip-plugin
插件。在父 pom.xml
或模块 pom.xml
中添加以下配置,来跳过特定模块的 deploy
阶段。
示例:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
5.5. 方法 5:临时跳过 deploy
阶段
如果你不想部署某个模块,但又不希望修改 pom.xml
或配置,可以临时使用 -DskipDeploy
来跳过部署:
mvn deploy -DskipDeploy
5.6. 方法 6:使用 mvn install
而不是 deploy
如果你在某个模块不需要将其部署到远程仓库,只是本地构建并安装到本地仓库,可以使用 install
代替 deploy
:
mvn install
这样该模块会被安装到本地仓库,而不会部署到远程仓库。
6. Maven package 的时候跳过测试。
在使用 mvn package
时,如果你希望跳过测试阶段(即不执行单元测试),可以通过以下几种方式来实现:
6.1. 使用 -DskipTests
参数
这是最常用的方式,使用 -DskipTests
参数来跳过测试的执行。该命令只会跳过测试的执行,而不会跳过编译测试代码。
mvn package -DskipTests
-DskipTests
:跳过测试执行,测试代码会被编译,但不会运行。
6.2. 使用 -Dtest=false
参数
另一种方式是使用 -Dtest=false
参数,这会告诉 Maven 不执行任何测试。
mvn package -Dtest=false
-Dtest=false
:强制不执行测试,不会运行任何测试类。
6.3. 使用 -Dmaven.test.skip=true
参数
如果你希望完全跳过测试,包括测试代码的编译和执行,可以使用 -Dmaven.test.skip=true
参数。这会跳过测试的所有阶段,包括编译和执行测试。
mvn package -Dmaven.test.skip=true
-Dmaven.test.skip=true
:完全跳过测试阶段(包括测试的编译和执行)。
6.4. 在 pom.xml
中配置跳过测试
如果你希望在构建过程中总是跳过测试,可以在 pom.xml
中配置跳过测试的属性。
在 pom.xml
文件中添加以下配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
6.5. Maven跳过总结
- 使用
-DskipTests
:跳过测试执行,但编译测试代码。 - 使用
-Dtest=false
:完全跳过测试,不执行任何测试类。 - 使用
-Dmaven.test.skip=true
:完全跳过测试的编译和执行。 - 在
pom.xml
中配置maven-surefire-plugin
,永久跳过测试。