本文主要内容来源于官网。
使用jdk1.8、maven3.8.4版本。
简介
maven是一个自动化构建工具,用来做项目构建和管理,应用于java平台。
早期的项目很多Ant项目,而JAR包的管理都是通过CVS管理,项目维护起来很麻烦。
The result is a tool that can now be used for building and managing any Java-based project. We hope that we have created something that will make the day-to-day work of Java developers easier and generally help with the comprehension of any Java-based project.
maven的目标就是使开发者在短时间内了解开发中的状态。关注:
- 简化构建过程,maven可以在一定程度上让开发者不必了解更多细节。
- 提供统一的构建系统,maven通过POM(project object model )项目对象模型)和一组插件完成项目构建,其中POM就是maven pom.xml,是xml格式的描述项目信息、开发者信息、依赖关系等一系列信息的文件,作为开发者如果熟悉了一个maven项目,那么就会了解所有的maven项目的构建。制定标准,在很大程度上节约了浏览项目的时间。
- 提供有优质的项目信息,maven中的POM提供这些项目信息一个很重要的信息就是依赖信息,还可以提供测试报告。
- 为开发实践提供指导,如项目结构、项目发布流程、单元测试规范等。
我们现在应用maven主要在于依赖管理、持续集成包括编译、构建、发布等。
下载
maven下载地址:maven.apache.org/download.cg…
配置安装
预设环境
maven 3.3及以上版本需要jdk1.7及以上版本。
$ echo $JAVA_HOME
C:\Program Files\Java\jdk1.8.0_251
安装及配置
- 配置maven安装目录,变量
MAVEN_HOME,如D:\develop\maven\apache-maven-3.8.4 - 配置maven bin目录,可以全局使用mvn命令,在
Path变量下增加%MAVEN_HOME%\bin
检查
# 查看版本
$ mvn -v
Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537)
Maven home: D:\develop\maven\apache-maven-3.8.4
Java version: 1.8.0_251, vendor: Oracle Corporation, runtime: C:\Program Files\Java\jdk1.8.0_251\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
原型
原型为maven提供了一套项目模板及工具。在eclipse、idea或者命令行创建maven项目时都会用到原型。
原型的设计思想是为maven提供统一的项目结构,加快开发速度。
使用原型需要调用构建目标mvn archetype:generate。
组成
maven的原型在jar包中的,包含了原型信息和 Velocity模板。
列表
maven提供了一系列原型。
| 项目标识 | 描述 |
|---|---|
| maven-archetype-archetype | An archetype to generate a sample archetype. |
| maven-archetype-j2ee-simple | An archetype to generate a simplifed sample J2EE application. |
| maven-archetype-plugin | An archetype to generate a sample Maven plugin. |
| maven-archetype-plugin-site | An archetype to generate a sample Maven plugin site. |
| maven-archetype-portlet | An archetype to generate a sample JSR-268 Portlet. |
| maven-archetype-quickstart | 生成简单的maven项目。 |
| maven-archetype-simple | An archetype to generate a simple Maven project. |
| maven-archetype-site | An archetype to generate a sample Maven site which demonstrates some of the supported document types like APT, Markdown, XDoc, and FML and demonstrates how to i18n your site. |
| maven-archetype-site-simple | An archetype to generate a sample Maven site. |
| maven-archetype-site-skin | An archetype to generate a sample Maven Site Skin. |
| maven-archetype-webapp | An archetype to generate a sample Maven Webapp project. |
创建一个项目
先创建一个项目,方便后续的操作。
新建项目
使用maven的原型插件maven-archetype-plugin创建新项目,关于原型在后面章节介绍。
其中:-DgroupId、-DartifactId、-DarchetypeArtifactId、-DarchetypeVersion分别指定了组织、项目标识、原型、版本,使用-DinteractiveMode关闭互动模式,命令执行后不需要手动设置。
- -D 参数设置系统属性,maven使用java的参数设置,向jvm加入参数。
$ mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
[INFO] Scanning for projects...
......
......
......
[INFO] Using following parameters for creating project from Archetype: maven-archetype-quickstart:1.4
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.mycompany.app
[INFO] Parameter: artifactId, Value: my-app
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.mycompany.app
[INFO] Parameter: packageInPathFormat, Value: com/mycompany/app
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.mycompany.app
[INFO] Parameter: groupId, Value: com.mycompany.app
[INFO] Parameter: artifactId, Value: my-app
[INFO] Project created from Archetype in dir: D:\workspace\tmp\my-app
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.415 s
[INFO] Finished at: 2022-03-12T17:55:41+08:00
[INFO] ------------------------------------------------------------------------
新生成项目目录结构,在window下使用tree命令查看:
D:.
│ pom.xml
│
└─src
├─main
│ └─java
│ └─com
│ └─mycompany
│ └─app
│ App.java
│
└─test
└─java
└─com
└─mycompany
└─app
AppTest.java
目录说明
maven的一个特性为开发实践提供指定,其中包括项目结构。通用的项目结构,可以让开发人员快速熟悉项目
src/main/java | 应用源文件 |
src/main/resources | 应用资源文件 |
src/main/filters | 资源过滤文件 |
src/main/webapp | web应用源文件 |
src/test/java | 测试源文件 |
src/test/resources | 测试资源文件 |
src/test/filters | 测试资源过滤文件 |
src/it | 集成测试文件 |
src/assembly | 打包描述 |
src/site | 站点 |
LICENSE.txt | 项目许可证 |
NOTICE.txt | 提示和依赖说明 |
README.txt | 项目间接、安装等信息 |
POM
POM(Project Object Model) 项目对象模型,将maven项目信息存储在xml文件pom.xml中。
项目中信息包括开发人员、缺陷跟踪、组织、许可证、项目URL、依赖关系等。
目前pom的版本是4.0.0
最小pom
pom.xml 文件必须的节点:
-
project根节点 -
modelVersion版本,固定4.0.0 -
groupId组织,一般根据域名取 -
artifactId项目 -
version版本
例:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</project>
groupId、artifactId、version定义了应用包在仓库中的位置,实例中组件包的名称为com.mycompany.app:my-app:1。
Super POM
maven默认pom.xml,正常情况下项目的所有pom都继承自Super POM。
查看Super POM 的方法是:
- 创建一个最小pom.xml
- 在最小pom.xml目录执行命令
mvn help:effective-pom
例:
$ mvn help:effective-pom
[INFO] Scanning for projects...
......
......
......
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-help-plugin:3.2.0:effective-pom (default-cli) @ my-app ---
[INFO]
Effective POMs, after inheritance, interpolation, and profiles are applied:
<?xml version="1.0" encoding="GBK"?>
<!-- ====================================================================== -->
<!-- -->
<!-- Generated by Maven Help Plugin on 2022-03-12T18:01:04+08:00 -->
<!-- See: http://maven.apache.org/plugins/maven-help-plugin/ -->
<!-- -->
<!-- ====================================================================== -->
<!-- ====================================================================== -->
<!-- -->
<!-- Effective POM for project 'com.mycompany.app:my-app:jar:1.0-SNAPSHOT' -->
<!-- -->
<!-- ====================================================================== -->
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://www.example.com</url>
<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
</pluginRepository>
</pluginRepositories>
<build>
<sourceDirectory>D:\workspace\tmp\my-app\src\main\java</sourceDirectory>
<scriptSourceDirectory>D:\workspace\tmp\my-app\src\main\scripts</scriptSourceDirectory>
<testSourceDirectory>D:\workspace\tmp\my-app\src\test\java</testSourceDirectory>
<outputDirectory>D:\workspace\tmp\my-app\target\classes</outputDirectory>
<testOutputDirectory>D:\workspace\tmp\my-app\target\test-classes</testOutputDirectory>
<resources>
<resource>
<directory>D:\workspace\tmp\my-app\src\main\resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>D:\workspace\tmp\my-app\src\test\resources</directory>
</testResource>
</testResources>
<directory>D:\workspace\tmp\my-app\target</directory>
<finalName>my-app-1.0-SNAPSHOT</finalName>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>default-clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>default-testResources</id>
<phase>process-test-resources</phase>
<goals>
<goal>testResources</goal>
</goals>
</execution>
<execution>
<id>default-resources</id>
<phase>process-resources</phase>
<goals>
<goal>resources</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>default-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<executions>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<executions>
<execution>
<id>default-install</id>
<phase>install</phase>
<goals>
<goal>install</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<executions>
<execution>
<id>default-deploy</id>
<phase>deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
<executions>
<execution>
<id>default-site</id>
<phase>site</phase>
<goals>
<goal>site</goal>
</goals>
<configuration>
<outputDirectory>D:\workspace\tmp\my-app\target\site</outputDirectory>
<reportPlugins>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</reportPlugin>
</reportPlugins>
</configuration>
</execution>
<execution>
<id>default-deploy</id>
<phase>site-deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
<configuration>
<outputDirectory>D:\workspace\tmp\my-app\target\site</outputDirectory>
<reportPlugins>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</reportPlugin>
</reportPlugins>
</configuration>
</execution>
</executions>
<configuration>
<outputDirectory>D:\workspace\tmp\my-app\target\site</outputDirectory>
<reportPlugins>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</reportPlugin>
</reportPlugins>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<outputDirectory>D:\workspace\tmp\my-app\target\site</outputDirectory>
</reporting>
</project>
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.163 s
[INFO] Finished at: 2022-03-12T18:01:04+08:00
[INFO] ------------------------------------------------------------------------
主要标签说明
基本标签
groupId
组织名
artifactId
项目标识
version
版本
packaging
支持pom, jar, maven-plugin, ejb, war, ear, rar ,默认值为 jar,不同类型定义了不同的构建目标。
POM 关系
pom中项目间的关系包含三种依赖、继承、聚合。
依赖关系
一个项目依赖于另一个项目构建及运行。
dependencies
一系列的依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<type>jar</type>
<scope>test</scope>
<optional>true</optional>
</dependency>
...
</dependencies>
depnedency
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<type>jar</type>
<scope>test</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
groupId、artifactId、version前面已经提到,定义了应用包在仓库中的位置。
type
默认为jar,一般是依赖文件的扩展名
classifier
分类,用于groupId、artifactId、version相同,内容不同的情况。打包后标识位于GAV之后,也就是version之后,例如,用maven-install-plugin插件将包安装到本地仓库。下面实例是将jar包安装到本地,指定-Dclassifier=1.8,其中
$ mvn install:install-file -Dclassifier=1.8 -DskipTests=true -Dfile=D:/develop/maven/repository/commons-io/commons-io/2.11.0/commons-io-2.11.0.jar -DgroupId=commons-io -DartifactId=commons-io -Dversion=2.11.0 -Dpackaging=jar
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install-file (default-cli) @ my-app ---
[INFO] Installing D:\develop\maven\repository\commons-io\commons-io\2.11.0\commons-io-2.11.0.jar to D:\develop\maven\repository\commons-io\commons-io\2.11.0\commons-io-2.11.0-1.8.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.709 s
[INFO] Finished at: 2022-03-12T18:03:42+08:00
[INFO] ------------------------------------------------------------------------
scope
作用域,指定了编译、运行、测试期间的classpath,也限制了依赖的传递性,包括:
-
compile 默认的作用域范围,未指定时使用这个值。在**所有classpath(编译、运行、测试)**下都是有效的,依赖关系会传递到依赖项目。
-
provided 与compile类似,此作用域表示期望依赖由JDK或者容器提供。只在编译和测试阶段的classpath中,不可传递依赖。例如,servlet-api由容器提供。
-
runtime 此作用域表示在编译期不需要此依赖,在运行时需要依赖项。在运行和测试阶段的classpath中,不在编译阶段的classpath中。例如,jdbc驱动。
-
test 此作用域表示应用正常使用不需要的依赖项,只在测试和执行阶段的classpath中,不可传递依赖。例如,junit单元测试包。
-
system 此作用域与provided类似,只在编译和测试阶段的classpath中,但必须显式的指定依赖包,不由maven查找。
systemPath
作用域指定为system时使用此标签。路径必须是绝对路径。官方建议使用变量,例如,${java.home}/lib
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>my-core</artifactId>
<scope>system</scope>
<version>1.0.1</version>
<systemPath>${java.home}\lib\my-core.jar</systemPath>
</dependency>
optional
一个项目本身是依赖项,将自身依赖标识为可选。如果项目A依赖于项目B来在编译一部分代码,但在运行期不需要这部分代码,那么B项目可能不需要被引入。
-
=> 表示必须依赖
-
-->表示可选依赖
项目X依赖于A,项目A依赖于B,构建A时,关系为A=>B,构建X时,关系为X=>A-->B,正常情况下X中将不包含B依赖包,如果需要B依赖,则需要加
optional移除或改成false,也可以在X中单独引入B依赖。
version
定义了依赖项的版本需求。软需求(Soft requirements )可以被依赖树中其他地方具有相同的groupId、artifactId的不同版本替代。硬需求(Hard requirements)要求特定的一个或多个版本。例如:
- 1.0 软需求版本,如果在依赖树中更早的没有其他版本出现,则使用1.0版本
- [1.0] 硬需求版本,只能使用1.0版本
- (,1.0] 硬需求版本,只能使用<=1.0版本
- [1.2,1.3] 硬需求版本,只能使用介于1.2和1.3的版本
- [1.0,2.0) 硬需求版本,只能使用1.0<=version<2.0
- [1.5,) 硬需求版本,只能使用>=1.5
- (,1.0],[1.2,) 硬需求版本,只能使用version<1.0 或者 version>=1.2,多个版本需求用逗号隔开
- (,1.1),(1.1,) 硬需求版本,任何非1.1版本
maven会选择所有满足硬需求的依赖的最高版本,如果没有依赖满足所有硬需求,构建失败。
当找不到任何版本信息时,在idea中maven会提示错误,如:
<!-- 大额存单facade包 -->
<dependency>
<groupId>com.csii.pcbs</groupId>
<artifactId>de-facade</artifactId>
<version>[1.3,1.4]</version>
</dependency>
提示:
No versions avaliable for com.csii.pcbs:de-facade:jar:[1.3,1.4] within spercified range
版本顺序:
何为高版本,何为低版本?
对于纯数字的,1.0、1.2、1.3等很明显,但是对于其他的不一定很好判定。
官网给出了很多案例,此处不详细描述。参考:maven.apache.org/pom.html
可以使用maven提供的工具检查版本顺序:
# 本地使用的maven 3.8.4
$ java -jar ${MAVEN_HOME}/lib/maven-artifact-3.8.4.jar 1.2 3 1-a 3-a 2-c 1.5
Display parameters as parsed by Maven (in canonical form and as a list of tokens) and comparison result:
1. 1.2 -> 1.2; tokens: [1, 2]
1.2 < 3
2. 3 -> 3; tokens: [3]
3 > 1-a
3. 1-a -> 1-a; tokens: [1, [a]]
1-a < 3-a
4. 3-a -> 3-a; tokens: [3, [a]]
3-a > 2-c
5. 2-c -> 2-c; tokens: [2, [c]]
2-c > 1.5
6. 1.5 -> 1.5; tokens: [1, 5]
关于正式版本和快照版本,参考版本及快照
exclusions
排除依赖项,不使用依赖的依赖项即排除指定的传递依赖。如果需要排除多个,则增加多个exclusion
exclusion
此标签可以有效的排除一些传递依赖,每个标签下包含groupId和artifactId。
排除依赖的原因在于:
- 原有的传递依赖项指定的
scope作用域不正确,需要排除,引入新的依赖项 - 原有的传递依赖项和项目中其他的依赖项存在冲突,冲突会导致项目找不到对应的类或者使用错误的依赖版本,需要排除,显式的引入依赖项。
下面实例:排除org.apache.maven:maven-embedder:2.0包下的org.apache.maven:maven-core依赖
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>2.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
</exclusion>
</exclusions>
</dependency>
与optional的差异:
optional是排除自身,optional修饰的依赖,可能被引入,也可能不被引入;exlcusions/exlcusion排除传递依赖,排除的是下一级的依赖。
optional示例
pcbs平台测试包com.csii.pcbs:pcbs-aplt-test依赖于org.springframework:spring-test
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.csii.pcbs</groupId>
<artifactId>pcbs-aplt-test</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
flowchart TD
pcbs-aplt-test(pcbs-aplt-test) -.可选依赖.-> spring-test(spring-test)
exlcusions/exlcusion示例
pcbs平台测试包com.csii.pcbs:dp-is-oltp依赖于com.csii.pcbs:pcbs-oltp-dependencies,com.csii.pcbs:pcbs-oltp-dependencies依赖于com.alibaba:dubbo和stax:stax-api
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.csii.pcbs</groupId>
<artifactId>dp-is-oltp</artifactId>
<dependencies>
<dependency>
<groupId>com.csii.pcbs</groupId>
<artifactId>pcbs-oltp-dependencies</artifactId>
<version>3.0.6</version>
<type>pom</type>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</exclusion>
<exclusion>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
flowchart TD
dp-is-oltp(dp-is-oltp) --> pcbs-oltp-dependencies(pcbs-oltp-dependencies)
pcbs-oltp-dependencies(pcbs-oltp-dependencies) --> com.alibaba(com.alibaba)
pcbs-oltp-dependencies(pcbs-oltp-dependencies) --> stax-api(stax-api)
dp-is-oltp(dp-is-oltp) -.传递依赖.-> com.alibaba(com.alibaba)
dp-is-oltp(dp-is-oltp) -.传递依赖.-> stax-api(stax-api)
继承关系
作为父项目,packaging要求必须为pom类型。关于Super POM 参考[Super POM](# Super POM)
简单使用
在父项目中定义:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<packaging>pom</packaging>
</project>
在子项目中引用:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.codehaus.mojo</groupId> <artifactId>my-parent</artifactId> <version>2.0</version> <!-- relativePath 非必须,优先查找此位置,之后才会查找本地仓库、远程仓库--> <relativePath>../my-parent</relativePath> </parent> <artifactId>my-project</artifactId></project>
子项目继承元素
子项目从父项目继承包括:
- groupId
- version
- description
- url
- inceptionYear
- organization
- licenses
- developers
- contributors
- mailingLists
- scm
- issueManagement
- ciManagement
- properties
- dependencyManagement
- dependencies
- repositories
- pluginRepositories
- build
- plugin executions with matching ids
- plugin configuration
- etc.
- reporting
- profiles
不继承元素:
- artifactId
- name
- prerequisites
dependencyManagement
用于管理依赖项。
在下面的示例中,父项目定义了dependencyManagement ,指定了org.codehaus.mojo:my-core这样一个依赖项,版本号1.0.0,子项目依赖了org.codehaus.mojo:my-core,但是未指定版本号,这时候maven可以自行填充版本号为1.0.0,不需要显式的指定依赖版本。但是,如果在子项目依赖中指定其他版本号,如2.0.0,那么子项目依赖的就是2.0.0。
在父项目中定义:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-core</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
在子项目中引用:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<!-- relativePath 非必须,优先查找此位置,之后才会查找本地仓库、远程仓库-->
<relativePath>../my-parent</relativePath>
</parent>
<artifactId>my-project</artifactId>
<dependencies>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-core</artifactId>
</dependency>
</dependencies>
</project>
dependencyManagement最大的意义在于能有有效的统一管理依赖项的版本。
需要注意:
-
传递依赖中的
version、scope也会被dependencyManagement管理,可能会导致一些问题,两个模块依赖了同一个依赖项但是版本不同,可能会出现版本冲突。这就需要用到之前提到的
exclusions/exclusion标签,进行排包操作。可以考虑使用maven-dependency-plugin插件,执行mvn dependency:tree,查看依赖树。 -
dependencyManagement下的依赖定义,如果未用到,则不会被引入。
聚合关系
简单使用
通过modules/module标签指定一系列模块,聚合项目可以聚合一系列模块的构建。
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<packaging>pom</packaging>
<modules>
<module>my-project</module>
<module>another-project</module>
<module>third-project/pom-example.xml</module>
</modules>
</project>
一个项目可以同时是父项目和聚合项目,也就是说,聚合项目可以被任何他所聚合的项目继承。也可以聚合不继承此项目的项目。
modules/module
模块的路径为相对路径。
properties
定义属性。采用占位符的方式${x},在poml.xml的任何位置访问,对于子项目可以从父项目中继承此属性。
构建配置
build
TODO 这里什么也没写...
Profile配置
profile
profile在settings.xml和pom.xml都有体现。POM4.0新加入的特性,根据不同环境提供不同的配置。
其中activation可以在指定的环境下修改pom定义,例如:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
...
<profiles>
<profile>
<id>test</id>
<activation>
<activeByDefault>false</activeByDefault>
<jdk>1.5</jdk>
<os>
<name>Windows XP</name>
<family>Windows</family>
<arch>x86</arch>
<version>5.1.2600</version>
</os>
<property>
<name>sparrow-type</name>
<value>African</value>
</property>
<file>
<exists>${basedir}/file2.properties</exists>
<missing>${basedir}/file1.properties</missing>
</file>
</activation>
...
</profile>
</profiles>
</project>
依赖管理
依赖是maven重要的一部分,前面提到了依赖、继承、聚合,涉及了项目与项目、模块与模块,依赖关系可能会非常复杂。
依赖冲突
A依赖B,B依赖C 1.0 版本,A依赖C 2.0版本,B依赖的C的依赖也会传递给A,那么同时引入C的两个版本就会出现依赖冲突。
flowchart TD
A(A) --> B(B)
B(B) --> C(C)
A(A) --> C(C)
A(A) -.传递依赖.-> C(C)
传递依赖可能导致,最终应用包中会引入具有相同 groupId 、 artifactId ,但版本号不同的jar,而同名类只会加载一次,类加载不知道从哪个jar包里加载(取决于依赖在依赖树中的位置),导致加载到错误的包,运行期间出现异常。
依赖调节机制
原则:
-
路径最近优先
A=>C 2.0版本 A=>B=>C 1.2版本,优先选择C 2.0版本
flowchart TD A(A) --> B(B) B(B) --> C-v1.2(C-v1.2) A(A) --> C-v2.0(C-v2.0) -
最先声明有限
如果A=>B=>X A=>D=>C路径一致,B先声明,则会使用C 1.2版本
flowchart TD
A(A) --> B(B)
A(A) --> D(D)
B(B) --> C-v1.2(C-v1.2)
D(D) --> C-v2.0(C-v2.0)
-
同级依赖,后者覆盖前者
下面展示了 urs-facade 两个版本先后声明,1.0.2在前1.0-SNAPSHOT在后,使用后声明的1.0-SNAPSHOT,反过来,如果后声明1.0.2,则使用1.0.2
<dependencies> <dependency> <groupId>com.snb.urs</groupId> <artifactId>urs-facade</artifactId> <version>1.0.2</version> </dependency> <dependency> <groupId>com.snb.urs</groupId> <artifactId>urs-facade</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
依赖检查
可使用mvn dependency:tree -Dverbose检查冲依赖。其中:
omitted for duplicate表示重复依赖,例:org.aspectj:aspectjweaver:jar:1.9.6:compile - omitted for duplicate- omitted for conflict with 下x.x.x,表示冲突依赖,例:org.slf4j:slf4j-api:jar:1.7.25:compile - omitted for conflict with 1.7.30
$ mvn dependency:tree -Dverbose
[INFO] Scanning for projects...
[INFO]
......
......
[INFO] online.xiyusu:springnote:war:0.0.1-SNAPSHOT
[INFO] +- online.xiyusu:tipbook-core:jar:1.0-SNAPSHOT:compile
[INFO] | +- (org.springframework:spring-jdbc:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.aspectj:aspectjweaver:jar:1.9.6:compile - omitted for duplicate)
[INFO] | +- (ch.qos.logback:logback-core:jar:1.2.3:compile - omitted for duplicate)
[INFO] | +- (ch.qos.logback:logback-classic:jar:1.2.3:compile - omitted for duplicate)
[INFO] | \- (org.slf4j:slf4j-api:jar:1.7.30:compile - omitted for duplicate)
[INFO] +- online.xiyusu:tipbook-test:jar:1.0-SNAPSHOT:compile
[INFO] | +- (ch.qos.logback:logback-core:jar:1.2.3:compile - omitted for duplicate)
[INFO] | +- (ch.qos.logback:logback-classic:jar:1.2.3:compile - omitted for duplicate)
[INFO] | +- (org.slf4j:slf4j-api:jar:1.7.30:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-context:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | +- (junit:junit:jar:4.12:compile - omitted for duplicate)
[INFO] | \- (online.xiyusu:tipbook-core:jar:1.0-SNAPSHOT:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-core:jar:4.3.9.RELEASE:compile
[INFO] | \- (commons-logging:commons-logging:jar:1.2:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-beans:jar:4.3.9.RELEASE:compile
[INFO] | \- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-context:jar:4.3.9.RELEASE:compile
[INFO] | +- org.springframework:spring-aop:jar:4.3.9.RELEASE:compile
[INFO] | | +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | | \- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | \- org.springframework:spring-expression:jar:4.3.9.RELEASE:compile
[INFO] | \- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-context-support:jar:4.3.9.RELEASE:compile
[INFO] | +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-context:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | \- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-jdbc:jar:4.3.9.RELEASE:compile
[INFO] | +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | \- org.springframework:spring-tx:jar:4.3.9.RELEASE:compile
[INFO] | +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | \- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-webmvc:jar:4.3.9.RELEASE:compile
[INFO] | +- (org.springframework:spring-aop:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-context:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-expression:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | \- org.springframework:spring-web:jar:4.3.9.RELEASE:compile
[INFO] | +- (org.springframework:spring-aop:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-beans:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-context:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] | \- (org.springframework:spring-core:jar:4.3.9.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-test:jar:4.3.9.RELEASE:test
[INFO] | \- (org.springframework:spring-core:jar:4.3.9.RELEASE:test - omitted for duplicate)
[INFO] +- org.aspectj:aspectjweaver:jar:1.9.6:compile
[INFO] +- mysql:mysql-connector-java:jar:8.0.12:compile
[INFO] | \- com.google.protobuf:protobuf-java:jar:2.6.0:compile
[INFO] +- com.alibaba:druid:jar:1.2.5:compile
[INFO] +- org.apache.commons:commons-dbcp2:jar:2.5.0:compile
[INFO] | +- org.apache.commons:commons-pool2:jar:2.6.0:compile
[INFO] | \- (commons-logging:commons-logging:jar:1.2:compile - omitted for duplicate)
[INFO] +- commons-codec:commons-codec:jar:1.11:compile
[INFO] +- commons-logging:commons-logging:jar:1.2:compile
[INFO] +- javax.servlet:javax.servlet-api:jar:4.0.0:compile
[INFO] +- javax.servlet.jsp.jstl:jstl-api:jar:1.2:compile
[INFO] | +- javax.servlet:servlet-api:jar:2.5:compile
[INFO] | \- javax.servlet.jsp:jsp-api:jar:2.1:compile
[INFO] +- taglibs:standard:jar:1.1.2:compile
[INFO] +- org.freemarker:freemarker:jar:2.3.29:compile
[INFO] +- org.apache.kafka:kafka_2.13:jar:2.4.0:compile
[INFO] | +- (org.apache.kafka:kafka-clients:jar:2.4.0:compile - omitted for duplicate)
[INFO] | +- (com.fasterxml.jackson.core:jackson-databind:jar:2.10.0:compile - omitted for conflict with 2.10.1)
[INFO] | +- com.fasterxml.jackson.module:jackson-module-scala_2.13:jar:2.10.0:compile
[INFO] | | +- (org.scala-lang:scala-library:jar:2.13.1:compile - omitted for duplicate)
[INFO] | | +- (com.fasterxml.jackson.core:jackson-core:jar:2.10.0:compile - omitted for duplicate)
[INFO] | | +- (com.fasterxml.jackson.core:jackson-annotations:jar:2.10.0:compile - omitted for duplicate)
[INFO] | | +- (com.fasterxml.jackson.core:jackson-databind:jar:2.10.0:compile - omitted for duplicate)
[INFO] | | \- com.fasterxml.jackson.module:jackson-module-paranamer:jar:2.10.0:compile
[INFO] | | +- (com.fasterxml.jackson.core:jackson-databind:jar:2.10.0:compile - omitted for duplicate)
[INFO] | | \- com.thoughtworks.paranamer:paranamer:jar:2.8:compile
[INFO] | +- com.fasterxml.jackson.dataformat:jackson-dataformat-csv:jar:2.10.0:compile
[INFO] | | +- (com.fasterxml.jackson.core:jackson-databind:jar:2.10.0:compile - omitted for duplicate)
[INFO] | | +- (com.fasterxml.jackson.core:jackson-annotations:jar:2.10.0:compile - omitted for duplicate)
[INFO] | | \- (com.fasterxml.jackson.core:jackson-core:jar:2.10.0:compile - omitted for duplicate)
[INFO] | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.10.0:compile
[INFO] | | +- (com.fasterxml.jackson.core:jackson-core:jar:2.10.0:compile - omitted for duplicate)
[INFO] | | \- (com.fasterxml.jackson.core:jackson-databind:jar:2.10.0:compile - omitted for duplicate)
[INFO] | +- net.sf.jopt-simple:jopt-simple:jar:5.0.4:compile
[INFO] | +- com.yammer.metrics:metrics-core:jar:2.2.0:compile
[INFO] | | \- (org.slf4j:slf4j-api:jar:1.7.2:compile - omitted for conflict with 1.7.30)
[INFO] | +- org.scala-lang.modules:scala-collection-compat_2.13:jar:2.1.2:compile
[INFO] | | \- (org.scala-lang:scala-library:jar:2.13.0:compile - omitted for conflict with 2.13.1)
[INFO] | +- org.scala-lang.modules:scala-java8-compat_2.13:jar:0.9.0:compile
[INFO] | | \- (org.scala-lang:scala-library:jar:2.13.0:compile - omitted for conflict with 2.13.1)
[INFO] | +- org.scala-lang:scala-library:jar:2.13.1:compile
[INFO] | +- org.scala-lang:scala-reflect:jar:2.13.1:compile
[INFO] | | \- (org.scala-lang:scala-library:jar:2.13.1:compile - omitted for duplicate)
[INFO] | +- com.typesafe.scala-logging:scala-logging_2.13:jar:3.9.2:compile
[INFO] | | +- (org.scala-lang:scala-library:jar:2.13.0:compile - omitted for conflict with 2.13.1)
[INFO] | | +- (org.scala-lang:scala-reflect:jar:2.13.0:compile - omitted for conflict with 2.13.1)
[INFO] | | \- (org.slf4j:slf4j-api:jar:1.7.26:compile - omitted for conflict with 1.7.30)
[INFO] | +- (org.slf4j:slf4j-api:jar:1.7.28:compile - omitted for conflict with 1.7.30)
[INFO] | +- org.apache.zookeeper:zookeeper:jar:3.5.6:compile
[INFO] | | +- org.apache.zookeeper:zookeeper-jute:jar:3.5.6:compile
[INFO] | | | \- (org.apache.yetus:audience-annotations:jar:0.5.0:compile - omitted for duplicate)
[INFO] | | +- org.apache.yetus:audience-annotations:jar:0.5.0:compile
[INFO] | | +- io.netty:netty-handler:jar:4.1.42.Final:compile
[INFO] | | | +- io.netty:netty-common:jar:4.1.42.Final:compile
[INFO] | | | +- io.netty:netty-buffer:jar:4.1.42.Final:compile
[INFO] | | | | \- (io.netty:netty-common:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | | +- io.netty:netty-transport:jar:4.1.42.Final:compile
[INFO] | | | | +- (io.netty:netty-common:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | | | +- (io.netty:netty-buffer:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | | | \- io.netty:netty-resolver:jar:4.1.42.Final:compile
[INFO] | | | | \- (io.netty:netty-common:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | | \- io.netty:netty-codec:jar:4.1.42.Final:compile
[INFO] | | | +- (io.netty:netty-common:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | | +- (io.netty:netty-buffer:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | | \- (io.netty:netty-transport:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | +- io.netty:netty-transport-native-epoll:jar:4.1.42.Final:compile
[INFO] | | | +- (io.netty:netty-common:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | | +- (io.netty:netty-buffer:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | | +- (io.netty:netty-transport:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | | \- io.netty:netty-transport-native-unix-common:jar:4.1.42.Final:compile
[INFO] | | | +- (io.netty:netty-common:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | | +- (io.netty:netty-buffer:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | | \- (io.netty:netty-transport:jar:4.1.42.Final:compile - omitted for duplicate)
[INFO] | | \- (org.slf4j:slf4j-api:jar:1.7.25:compile - omitted for conflict with 1.7.30)
[INFO] | \- commons-cli:commons-cli:jar:1.4:compile
[INFO] +- org.apache.kafka:kafka-clients:jar:2.4.0:compile
[INFO] | +- com.github.luben:zstd-jni:jar:1.4.3-1:compile
[INFO] | +- org.lz4:lz4-java:jar:1.6.0:compile
[INFO] | +- org.xerial.snappy:snappy-java:jar:1.1.7.3:compile
[INFO] | \- (org.slf4j:slf4j-api:jar:1.7.28:compile - omitted for conflict with 1.7.30)
[INFO] +- com.fasterxml.jackson.core:jackson-core:jar:2.10.1:compile
[INFO] +- com.fasterxml.jackson.core:jackson-databind:jar:2.10.1:compile
[INFO] | +- (com.fasterxml.jackson.core:jackson-annotations:jar:2.10.1:compile - omitted for duplicate)
[INFO] | \- (com.fasterxml.jackson.core:jackson-core:jar:2.10.1:compile - omitted for duplicate)
[INFO] +- com.fasterxml.jackson.core:jackson-annotations:jar:2.10.1:compile
[INFO] +- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] | +- (ch.qos.logback:logback-core:jar:1.2.3:compile - omitted for duplicate)
[INFO] | \- (org.slf4j:slf4j-api:jar:1.7.25:compile - omitted for conflict with 1.7.30)
[INFO] +- org.slf4j:slf4j-api:jar:1.7.30:compile
[INFO] +- junit:junit:jar:4.12:test (scope not updated to compile)
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] \- org.testng:testng:jar:6.14.3:test
[INFO] +- com.beust:jcommander:jar:1.72:test
[INFO] \- org.apache-extras.beanshell:bsh:jar:2.0b6:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 19.488 s
[INFO] Finished at: 2022-02-18T01:23:35+08:00
[INFO] ------------------------------------------------------------------------
依赖调整
- 根据
dependencies/dependency中的scope调整。 - 根据
dependencies/dependency中的optional,将依赖设置为可选依赖。 - 根据
exlcusions/exlcusion进行排包(主要方法)。
版本及快照
快照是某一时间点的项目进度或者版本。
在正常项目开发过程中,开发阶段项目内容处于不稳定状态,项目版本不断迭代,一个项目A依赖另一个项目B,项目B不断更新依赖包,并发到仓库中,于此同时项目A就要不断更新B项目的依赖,不断修改版本号造成了人员浪费。maven提供的快照解决了者一问题。需注意:
- 快照版本是以
-SNAPSHOT结尾的版本。 - 与快照版本对应的是
RELEASE,发布版本或者正式版本,非快照版本即为正式版本。 - 快照版本在
deploy时可以覆盖远程仓库版本,本地打包引用依赖时可以获取最新的快照版本,而不需要修改版本号。 - 正常远程仓库可设置正式版是否允许覆盖,一般来说远程仓库正式版本不允许覆盖,如有更新需升级版本号。
- 快照版本由于可覆盖特性,如果在生产环境使用,容易出现风险,将测试代码发布到生产,因此生产环境要求使用正式版本。
构建生命周期
生命周期
maven构建生命周期(Lifecycle)有三个生命周期default、clean、site
default生命周期进行项目部署clean生命周期进行项目清理site生命周期进行项目站点创建
构建阶段
构建生命周期(Lifecycle)由一组构建阶段(Phase)组成。
插件目标
构建阶段(Phase)由一组插件目标(goal)组成。
插件目标是一个特定的任务,比构件阶段更加精细化。可以绑定零个或多个构建阶段,未绑定构建阶段的目标可以在构建生命周期之外执行,执行顺序取决于调用目标和构建阶段。例如:dependency:copy dependencies,下面的示例,先执行clean 阶段,然后是dependency:copy dependencies目标,最后执行package。
mvn clean dependency:copy dependencies package
如果插件目标被绑定在构件阶段,那么在这些阶段对应执行。
详述生命周期
Clean Lifecycle
| 阶段 | 描述 |
|---|---|
pre-clean | 执行项目清理前所需要的流程。 |
clean | 移除所有之前生成的文件 |
post-clean | 执行项目清理后所需要的流程。 |
Default Lifecycle
主要完成校验项目、编译资源、测试、打包生成二进制文件(jar等)、集成测试、安装包到本地目录、部署已安装的包到远程仓库。
构建阶段
| 阶段 | 描述 |
|---|---|
validate | 验证项目是正确的并且所有必须信息是可用的。 |
initialize | initialize build state, e.g. set properties or create directories. |
generate-sources | generate any source code for inclusion in compilation. |
process-sources | process the source code, for example to filter any values. |
generate-resources | generate resources for inclusion in the package. |
process-resources | copy and process the resources into the destination directory, ready for packaging. |
compile | 编译项目源码 |
process-classes | post-process the generated files from compilation, for example to do bytecode enhancement on Java classes. |
generate-test-sources | generate any test source code for inclusion in compilation. |
process-test-sources | process the test source code, for example to filter any values. |
generate-test-resources | create resources for testing. |
process-test-resources | copy and process the resources into the test destination directory. |
test-compile | compile the test source code into the test destination directory |
process-test-classes | post-process the generated files from test compilation, for example to do bytecode enhancement on Java classes. |
test | 使用合适的单元测试框架执行测试。测试不要求打包和部署代码。Junit等。 |
prepare-package | perform any operations necessary to prepare a package before the actual packaging. This often results in an unpacked, processed version of the package. |
package | 将编译好的源码打包,一般会生成在项目下的target目录 |
pre-integration-test | perform actions required before integration tests are executed. This may involve things such as setting up the required environment. |
integration-test | process and deploy the package if necessary into an environment where integration tests can be run. |
post-integration-test | perform actions required after integration tests have been executed. This may including cleaning up the environment. |
verify | 检查确认包是合法且符合质量标准的。 |
install | 将包安装到本地,作为本地其他项目的依赖项。 |
deploy | 将包发布到远程仓库,供其他开发者和项目使用。 |
package、install、deploy
package 打包到项目target目录;
install 打包到项目target目录、本地仓库;
deploy 打包到项目target目录、本地仓库、远程仓库;
mvn clean package 依次执行了clean、resources、compile、testResources、testCompile、test、jar7个阶段。
$ mvn clean package
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- `maven-clean-plugin:3.1.0:clean` (default-clean) @ my-app ---
[INFO] Deleting D:\workspace\tmp\my-app\target
[INFO]
[INFO] --- `maven-resources-plugin:3.0.2:resources` (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tmp\my-app\src\main\resources
[INFO]
[INFO] --- `maven-compiler-plugin:3.8.0:compile` (default-compile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\workspace\tmp\my-app\target\classes
[INFO]
[INFO] --- `maven-resources-plugin:3.0.2:testResources` (default-testResources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tmp\my-app\src\test\resources
[INFO]
[INFO] --- `maven-compiler-plugin:3.8.0:testCompile` (default-testCompile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\workspace\tmp\my-app\target\test-classes
[INFO]
[INFO] --- `maven-surefire-plugin:2.22.1:test` (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.016 s - in com.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ my-app ---
[INFO] Building jar: D:\workspace\tmp\my-app\target\my-app-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.981 s
[INFO] Finished at: 2022-03-12T18:14:58+08:00
[INFO] ------------------------------------------------------------------------
mvn clean install 依次执行了clean、resources、compile、testResources、testCompile、test、jar、install 8个阶段。
$ mvn clean install
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- `maven-clean-plugin:3.1.0:clean` (default-clean) @ my-app ---
[INFO] Deleting D:\workspace\tmp\my-app\target
[INFO]
[INFO] --- `maven-resources-plugin:3.0.2:resources` (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tmp\my-app\src\main\resources
[INFO]
[INFO] --- `maven-compiler-plugin:3.8.0:compile` (default-compile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\workspace\tmp\my-app\target\classes
[INFO]
[INFO] --- `maven-resources-plugin:3.0.2:testResources` (default-testResources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tmp\my-app\src\test\resources
[INFO]
[INFO] --- `maven-compiler-plugin:3.8.0:testCompile` (default-testCompile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\workspace\tmp\my-app\target\test-classes
[INFO]
[INFO] --- `maven-surefire-plugin:2.22.1:test` (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.032 s - in com.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- `maven-jar-plugin:3.0.2:jar` (default-jar) @ my-app ---
[INFO] Building jar: D:\workspace\tmp\my-app\target\my-app-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- `maven-install-plugin:2.5.2:install` (default-install) @ my-app ---
[INFO] Installing D:\workspace\tmp\my-app\target\my-app-1.0-SNAPSHOT.jar to D:\develop\maven\repository\com\mycompany\app\my-app\1.0-SNAPSHOT\my-app-1.0-SNAPSHOT.jar
[INFO] Installing D:\workspace\tmp\my-app\pom.xml to D:\develop\maven\repository\com\mycompany\app\my-app\1.0-SNAPSHOT\my-app-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.047 s
[INFO] Finished at: 2022-03-12T18:16:43+08:00
[INFO] ------------------------------------------------------------------------
mvn clean deploy 依次执行了clean、resources、compile、testResources、testCompile、test、jar、install、deploy9个阶段。
$ mvn clean deploy
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- `maven-clean-plugin:3.1.0:clean` (default-clean) @ my-app ---
[INFO] Deleting D:\workspace\tmp\my-app\target
[INFO]
[INFO] --- `maven-resources-plugin:3.0.2:resources` (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tmp\my-app\src\main\resources
[INFO]
[INFO] --- `maven-compiler-plugin:3.8.0:compile` (default-compile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\workspace\tmp\my-app\target\classes
[INFO]
[INFO] --- `maven-resources-plugin:3.0.2:testResources ``(default-testResources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\workspace\tmp\my-app\src\test\resources
[INFO]
[INFO] --- `maven-compiler-plugin:3.8.0:testCompile` (default-testCompile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\workspace\tmp\my-app\target\test-classes
[INFO]
[INFO] --- `maven-surefire-plugin:2.22.1:test` (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.016 s - in com.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- `maven-jar-plugin:3.0.2:jar` (default-jar) @ my-app ---
[INFO] Building jar: D:\workspace\tmp\my-app\target\my-app-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- `maven-install-plugin:2.5.2:install` (default-install) @ my-app ---
[INFO] Installing D:\workspace\tmp\my-app\target\my-app-1.0-SNAPSHOT.jar to D:\develop\maven\repository\com\mycompany\app\my-app\1.0-SNAPSHOT\my-app-1.0-SNAPSHOT.jar
[INFO] Installing D:\workspace\tmp\my-app\pom.xml to D:\develop\maven\repository\com\mycompany\app\my-app\1.0-SNAPSHOT\my-app-1.0-SNAPSHOT.pom
[INFO]
[INFO] --- `maven-deploy-plugin:2.8.2:deploy` (default-deploy) @ my-app ---
[INFO] ------------------------------------------------------------------------
......
Site Lifecycle
| 阶段 | 描述 |
|---|---|
pre-site | execute processes needed prior to the actual project site generation |
site | generate the project's site documentation |
post-site | execute processes needed to finalize the site generation, and to prepare for site deployment |
site-deploy | deploy the generated site documentation to the specified web server |
站点
以web形式展示项目信息
$ mvn site
语法规则
mvn Phase plugin:goal
仓库
早期的jar包管理,可能就放在项目lib下,也可能放在svn上。maven提供了仓库的概念。
仓库是maven中存储管理JAR包的地方,可以分为本地仓库、远程仓库(包括中央仓库、其他第三方仓库、局域网仓库),远程仓库提供了依赖包的上传及下载功能 。
本地仓库
本地存储JAR包的目录,是maven依赖包获取目录。maven项目构建时,会从远程仓库拉取项目依赖的JAR包。本地仓库包含了从远程仓库拉取的依赖包、也包括本地构建生成的依赖包,本地构建生成的包属于未发布的临时包。本地仓库的包可随时被覆盖,关于maven构建命令参考 构建生命周期。
<settings>
<localRepository>D:/localRepository</localRepository>
</settings>
远程仓库
远程仓库是指不在本机的仓库,可通过一系列网络协议远程访问。其中由maven社区维护的仓库叫中央仓库,由其他公司或社区维护的仓库,对外提供依赖下载服务为第三方仓库,如阿里镜像仓库、华为镜像仓库等。还有一部分仓库也是由公司维护,但仅限于对内部提供依赖下载及私有依赖的管理。
<repositories>
<repository>
<id>my-repo1</id>
<name>your custom repo</name>
<url>http://jarsm2.dyndns.dk</url>
</repository>
<repository>
<id>my-repo2</id>
<name>your custom repo</name>
<url>http://jarsm2.dyndns.dk</url>
</repository>
</repositories>
局域网的仓库,可通过nexus搭建。
仓库配置
全局配置
配置默认路径:${maven.home}/conf/settings.xml,其中${maven.home}指maven的安装目录。
<settings>
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>
http://10.0.128.16:8081/nexus/content/groups/public/
</url>
</mirror>
</mirrors>
</settings>
用户配置
配置默认路径:${user.home}/.m2/settings.xml,其中${user.home}指用户目录。
<settings>
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>
http://10.0.128.16:8081/nexus/content/groups/public/
</url>
</mirror>
</mirrors>
</settings>
自定义配置
在项目下的pom.xml中配置仓库
<project>
...
<repositories>
<repository>
<id>my-repo1</id>
<name>your custom repo</name>
<url>http://jarsm2.dyndns.dk</url>
</repository>
<repository>
<id>my-repo2</id>
<name>your custom repo</name>
<url>http://jarsm2.dyndns.dk</url>
</repository>
</repositories>
...
</project>
settings.xml
maven使用了镜像(mirror),镜像仓库可以更快的同步、自由控制等。
mirrors下可以匹配多个镜像仓库,但是maven并不会聚合这些镜像,只会选择第一个匹配的。
mirrorOf 目的时拦截对远程仓库的请求。
*表示匹配所有镜像,意思时所有请求都会重定向到这个镜像所对应的urlexternal:*匹配所有非本地和文件协议的repo,repo1匹配 repo 或者 repo1*,!repo1匹配除了repo1
仓库关系
开放服务的第三方仓库有很多,如阿里仓库、华为仓库等。仓库可以通过https协议进行同步。
可以是这样(当然某些私服可能不与外部交互,不做同步需要,无源码的需要人工上传包):
flowchart TD
中央仓库(中央仓库) --> 远程仓库1(阿里镜像仓库)
中央仓库(中央仓库) --> 远程仓库2(华为镜像仓库)
中央仓库(中央仓库) --> 远程仓库3(网易镜像仓库)
远程仓库1(阿里镜像仓库) .-> 远程仓库(某私服仓库)
远程仓库2(华为镜像仓库) .-> 远程仓库(某私服仓库)
远程仓库3(网易镜像仓库) .-> 远程仓库(某私服仓库)
subgraph 某银行
远程仓库(某私服仓库) --> 本地仓库1(开发本地仓库1)
远程仓库(某私服仓库) --> 本地仓库2(开发本地仓库2)
远程仓库(某私服仓库) --> 本地仓库3(开发本地仓库3)
end
也可以是这样(这中时个人开发者,会自行选择速度较快的仓库):
flowchart TD
中央仓库(中央仓库) --> 远程仓库1(阿里镜像仓库)
中央仓库(中央仓库) --> 远程仓库2(华为镜像仓库)
中央仓库(中央仓库) --> 远程仓库3(网易镜像仓库)
远程仓库1(阿里镜像仓库) .-> 本地仓库(本地仓库)
远程仓库2(华为镜像仓库) .-> 本地仓库(本地仓库)
远程仓库3(网易镜像仓库) .-> 本地仓库(本地仓库)
仓库优先级
Remote repository URLs are queried in the following order for artifacts until one returns a valid result:
- effective settings:
- Global
settings.xml- User
settings.xml- local effective build POM:
- Local
pom.xml- Parent POMs, recursively
- Super POM
- effective POMs from dependency path to the artifact.
For each of these locations, the repositories within the profiles are queried first in the order outlined at Introduction to build profiles.
远程仓库URL查找优先级:
全局配置文件>用户配置文件>pom.xml>父级pom.xml>顶层 pom.xml>依赖中的 pom. xml
上述配置中,profile下的仓库被优先查找。
其他内容
核心存款系统pom.xml文件,参考附录[核心存款系统集成项目pom.xml](# 核心存款系统集成项目pom.xml)
插件
maven本质是个插件执行框架。
maven及第三方提供的插件,可以参考maven.apache.org/plugins/ind…
常见的插件
maven-archetype-plugin
原型插件,用来根据原型模板创建项目。
前面创建项目我们就是用的原型插件,需要调用mvn archetype:generate目标。
$ mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
maven-jar-plugin
maven-war-plugin
maven-assembly-plugin
maven-jetty-plugin
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.20.v20190813</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<webApp>
<contextPath>/note</contextPath>
</webApp>
</configuration>
</plugin>
推荐
pom.xml标签大全:菜鸟教程
写在最后
maven 知识点很多,本文只得皮毛,后续不定时补充。