本文主要内容来源于官网。
使用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>
复制代码