文章目录
- 0、跳过单元测试的两种姿势
- 1、mvn help:system
- 2、mvn archetype:generate
- 3、Maven scope
- 4、依赖冲突
- 5 替换掉pom中的property
- 6 如何让项目的版本号自增
- 7 mvn import 和 继承
0、跳过单元测试的两种姿势
-DskipTests,不执行测试用例,但编译测试用例类生成相应的class文件至target/test-classes下。
-Dmaven.test.skip=true,不执行测试用例,也不编译测试用例类。
1、mvn help:system
会从远程仓库拉取配置,展示所有的环境变量。排错神器
2、mvn archetype:generate
这个用的不是很多,主要用于生成一个空的项目工程。比如我们做个demo:
mvn archetype:generate -DgroupId=com.ht.test -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
mvn test
mvn clean package
java -cp my-app-1.0-SNAPSHOT.jar com.ht.test.App
如此就生成了一个 my-app
项目,并完成了单元测试、打包、运行。
为啥要介绍这个呢?因为这个命令相当于是一个代码生成器,在一些开源的项目中,使用该命令能快速搭建起一个project.
3、Maven scope
1)、为啥有个scope的概念?
因为maven 项目 有三套 classpath (JVM 运行的时候要去classpath下面加载对应的类)。
- maven在编译源码的时候有一套classpath;
- 在编译、执行测试代码的时候有一套classpath;
- 在运行项目的时候有一套classpath 。
maven scope就是用来控制依赖包和这三种classpath 的关系的。)。
2) <scope> runtime </scope>
表示 测试和运行 有效,但是编译的时候无效。 (和 Provided刚好相反) 典型应用如 mysql 驱动,我们写代码一般只会使用到 javax.sql 的接口,不会直接使用到 mysql 驱动的API。
话虽如此,还不如将 mysql驱动 scope 也设置为 compile ,省事,而且说不定就会使用 驱动的特定API。
3) <optional>true</optional>
表示依赖传递会失效,不会再往上传递。
比如A 依赖B,B依赖C(optional=true),那么A 不会依赖C。假如optional=false,根据依赖传递机制,A 会依赖C。
典型场景:有个通用数据访问层项目 ,可以接ES 、Hbase、Redis,这样就有三类依赖了,但其实是可以只用其一的,此时声明 optional=true 不要向上传递。
若 项目 X 依赖了 这个数据层项目,则可根据自己需求引入 ES、Hbase、Redis其中一个依赖,让B 跑起来。
4、依赖冲突
依赖冲突经常出现,表现就是 MethodNotFound 、ClassNotFound等,多数情况下是由 类冲突(依赖冲突)导致。
解决办法: mvn dependency:tree,然后该 exclude 就exclude 。不过也有比较坑的:公司的一个自研中间件,把某个低版本的开源组件给打到了一个 jar 里,然后项目除了依赖自研中间件外,还独立依赖了高版本的开源组件。在 Linux下,先加载自研中间件中组件,还是自己单独依赖的,可就不好说了。因此会在不同环境中、偶发地出现诡异的 XXNotFound .
5 替换掉pom中的property
mvn versions:set -DnewVersion=${release_version}
mvn versions:set-property -Dproperty=kafka.version -DnewVersion=${kafka_version}
mvn version:set-property -DautoLinkItems=false -Dproperty=my.boot.version -DnewVersion=${releaseVersion}
注意: -DautoLinkItems=false
, 这个参数的含义是: Whether properties linking versions should be auto-detected or not (default true)
.
这里也多说一句, 怎么用gradle
把包安装在本地库呢?给个deploy kafka 的例子:
./gradlew build -x test -x check
./gradlew uploadArchives -Pversion=${release_version}
6 如何让项目的版本号自增
可以使用versions-maven-plugin
插件,指定在package
阶段,自动将0.0.1
-> 0.0.2
。不过这个特性好像不是很好用,
自增的版本号不好管理,连我开发者本人都不知道当前哪个版本号是正确的。
窃以为还是上一节的更实用
7 mvn import 和 继承
springboot 推荐用户使用继承spring-boot-starter-parent
来定义依赖版本,不过当用户不希望继承这个模块,但是依然使用springboot 的依赖时, 可以这样处理:
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.12.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
不过呢, 这样做又没法使用 property
来覆盖个别依赖了, 这个时候,用户可以在定义 <import>
的这个依赖之前先定义别的依赖,比如说下面就指定了 Fowler-SR2 这个版本的 spring-data-redis 去覆盖 spring-boot-dependencies 中的 spring-data-redis
<dependencyManagement>
<dependencies>
<!-- Override Spring Data release train provided by Spring Boot -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>Fowler-SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.12.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
那么 import
究竟咋用呢? 这里给出一个英文解释:
import
This scope is only supported on a dependency of type pom in the <dependencyManagement> section. It
indicates the dependency to be replaced with the effective list of dependencies in the specified POM’s
<dependencyManagement> section. Since they are replaced, dependencies with a scope of import do not
actually participate in limiting the transitivity of a dependency.
import
只能用于 <dependencyManagement>
, 它将 spring-boot-dependencies
中 <dependencyManagement>
下的dependencies插入到当前工程的<dependencyManagement>
中,注意这样做是不存在依赖传递的.
假如没有import时,意思是将spring-boot-dependencies
的dependencies
全部插入到当前工程的dependencies
中,并且会依赖传递。