简介
- maven是一个声明式的项目管理工具;
- maven本身不能构建项目,是通过借助各个插件,并将插件的goal绑定到各个生命周期去执行来实现;
- maven通过引入唯一的四元组来定位依赖,并将其下载到本地仓库;
- 祖先pom是所有pom的默认祖先,里面定义了一系列默认值,包括path、插件,以及默认插件绑定的生命周期。
生命周期
maven的生命周期模式,个人理解为设计模式中的模板模式,即定义了生命周期运行的骨架,将各个阶段的实现延迟到具体的插件中。
maven常见的生命周期如下:
- default:编译源代码并处理打包项目相关的所有事情
阶段 | 解释 |
validate | 验证项目是正确的,所有必要信息都可用,所有依赖项都已下载 |
compile | 编译项目源代码 |
test | 使用适当的单元测试框架对编译后的源代码运行测试 |
package | 将编译后的代码打包成可发布格式,例如JAR |
install | 将包安装到本地存储库中,以便在本地的其他项目中作为依赖项使用 |
deploy | 将最终包复制到远程存储库,以便与其他开发人员和项目共享 |
- clean:清理构建输出,包括生成的编译类、JAR文件等
- site:为项目生成文档
实例——父项目
<?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>
# 下述四元组唯一定义了一个maven项目
<groupId>com.bytedance.ecom</groupId>
<artifactId>huskar</artifactId>
# 类型为pom
<packaging>pom</packaging>
<version>1.0.0</version>
# 子模块定义
<modules>
<module>huskar-web</module>
...
</modules>
# 配置的key-val值
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
...
<kafka-clients-version>0.10.1.2-bd1.7.5</kafka-clients-version>
</properties>
# 公共依赖版本定义
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.bytedance</groupId>
<artifactId>env-conf</artifactId>
<version>${bytedance-env-conf}</version>
</dependency>
...
</dependencies>
</dependencyManagement>
<build>
# 使用的插件/自定义默认插件
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version> <!-- or newer version -->
...
</configuration>
</plugin>
</plugins>
</build>
# 发布(deploy)的仓库
<distributionManagement>
<repository>
<id>bytedance-releases</id>
<url>http://maven.byted.org/repository/releases</url>
</repository>
...
</distributionManagement>
# 依赖的下载仓库
<repositories>
<repository>
<id>bytedance-snapshots</id>
<url>http://maven.byted.org/repository/snapshots</url>
</repository>
...
</repositories>
# 插件的下载仓库
<pluginRepositories>
<pluginRepository>
<id>bytedance-releases</id>
<url>https://maven.byted.org/repository/releases</url>
</pluginRepository>
...
</pluginRepositories>
</project>
实例——模块
<?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>
# 父pom,继承他的所有属性
<parent>
<artifactId>huskar</artifactId>
<groupId>com.bytedance.ecom</groupId>
<version>1.0.0</version>
</parent>
# groupId继承父pom,packaging默认为jar
<artifactId>huskar-web</artifactId>
<version>1.0.0</version>
# 依赖
<dependencies>
<dependency>
<groupId>com.bytedance.ecom</groupId>
<artifactId>huskar-biz</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<!--打包指令 : mvn package spring-boot:repackage -->
<build>
<finalName>${project.artifactId}-${project.version}</finalName>
<!--资源文件目录-->
<resources>
# 指定main/java目录下的mepper.xml等文件为配置文件
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.xml</include>
</includes>
# 是否替换资源文件中的占位符
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>com.bytedance</groupId>
<artifactId>cloud-mvn</artifactId>
<version>${cloud-mvn-version}</version>
# 执行命令
<executions>
<execution>
<id>toutiao cloud scm package</id>
# 绑定:将插件的repackage的goal绑定到validate阶段
<phase>validate</phase>
<goals>
<goal>repackage</goal>
</goals>
</execution>
...
</executions>
</plugin>
...
</plugins>
</build>
<!--profiles-->
# 配置,用来根据不同环境定义不同的pom属性
<profiles>
<profile>
<id>dev</id>
# 激活条件
<activation>
<activeByDefault>true</activeByDefault>
</activation>
# 这里可以填pom中的任意属性,进行覆盖,如<properties/>
</profile>
...
</profiles>
</project>
最佳实践
- maven不允许循环依赖;
- 在父pom中定义子模块的公共部分,如依赖配置(包括传递依赖)(dependencyManagement)、插件配置(pluginManagement)、公共依赖(dependencies)、公共插件(plugins)等。通常,将版本号信息额外做成map,保存在properties中;
- 由于兄弟依赖之间的版本号通常是同步的,使用project.version进行定义;
- 将项目中的直接依赖显式写在pom中,不要使用间接依赖,使用
mvn dependency:analyze
进行检查; - 如果需要同时依赖一个jar包的不同版本,使用maven-shade-plugin插件,为其中一个版本建立shade包(仅仅修改包名),并在pom中引用它;
- 为统一jdk编译版本,通常在maven-compiler-plugin中显式定义,如使用到了基于java的APT的类库,如lombok,需要在annotationProcessorPaths标签中进行定义。