写在前面
本文参考廖雪峰的在线教程: https://www.liaoxuefeng.com/wiki/1252599548343744/1255945359327200
一 介绍
1 作用
- 依赖管理机制。
- 标准化的项目结构;
- 配置环境(版本号等)
- 构建流程(编译,测试,打包,发布……);
2 Maven项目结构
(1) 基本结构
这些就是一个Maven项目的标准目录结构:
项目的根目录a-maven-project是项目名, 下面:
- 它有一个项目描述文件pom.xml
- 存放Java源码的目录是src/main/java
- 存放资源文件的目录是src/main/resources
- 存放测试源码的目录是src/test/java
- 存放测试资源的目录是src/test/resources
- 最后,所有编译、打包生成的文件都放在target目录里
(2) pom.xml 介绍
一个Maven工程就是由groupId,artifactId和version作为唯一标识:
groupId
类似于Java的包名,通常是公司或组织名称artifactId
类似于Java的类名,通常是项目名称version
该jar包的版本
3 安装
1 官网(https://maven.apache.org/download.cgi)下载 tar.gz 文件
2 解压到自定义的目录
3 配置环境变量
vim ~/.bash_profile
# Maven
export M2_HOME=/Users/jiangchengzhi/Downloads/local/apache-maven-3.8.5
export PATH=$PATH:$M2_HOME/bin
source ~/.bash-profile
4 查看是否安装成功
mvn -v
二 依赖管理
1 配置格式
在 pom.xml 中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.4.2.RELEASE</version>
</dependency>
2 依赖关系
(1) 如何设定?
<dependency>
下的 <version>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
<scope>runtime</scope> //focus here
</dependency>
(2) 种类
Maven定义了几种依赖关系,分别是compile、test、runtime和provided:
scope | 说明 | 例如 |
---|---|---|
compile (常用) | 编译时需要用到该jar包(默认) | commons-logging |
test | 编译Test时需要用到该jar包 | junit |
runtime | 编译时不需要,但运行时需要用到 | mysql (JDBC驱动) |
provided | 编译时需要用到,但运行时由JDK或某个服务器提供 | servlet-api |
其中,默认的compile是最常用的,Maven会把这种类型的依赖直接放入classpath。
3 依赖包的安装
(1) 搜索包
Maven维护了一个中央仓库(repo1.maven.org)
,所有第三方库将自身的jar以及相关信息上传至中央仓库,Maven就可以从中央仓库把所需依赖下载到本地。
(2) 配置包
上面的网站, 找到想要包, 然后找到配置项, 粘贴到自己的项目的 pom.xml 里去
(3) 安装包
mvn clean package
如果一切顺利,即可在target目录下获得编译后自动打包的jar。
(4) 常见问题
每次都需要下载吗?
Maven并不会每次都从中央仓库下载jar包。一个jar包一旦被下载过,就会被Maven自动缓存在本地目录(用户主目录的.m2
目录)
(5) Maven镜像
除了可以从Maven的中央仓库下载外,还可以从Maven的镜像仓库下载
应用:如果访问Maven的中央仓库非常慢,我们可以选择一个速度较快的Maven的镜像仓库。
在用户主目录下进入.m2
目录,创建一个settings.xml
配置文件,内容如下:
<settings>
<mirrors>
<mirror>
<id>aliyun</id>
<name>aliyun</name>
<mirrorOf>central</mirrorOf>
<!-- 国内推荐阿里云的Maven镜像 -->
<url>https://maven.aliyun.com/repository/central</url>
</mirror>
</mirrors>
</settings>
三 构建流程
1 结构总览
生命周期(lifecycle)
-分为若干个-> 阶段(phase)
-分为若干个-> Goal
lifecycle相当于Java的package,它包含一个或多个phase; phase相当于Java的class,它包含一个或多个goal; goal相当于class的method,它其实才是真正干活的。
2 常见结构
(1) lifecycle 下的 phase
default
- 内置的生命周期
包含以下phase:
validate
initialize
generate-sources
process-sources
generate-resources
process-resources
compile
process-classes
generate-test-sources
process-test-sources
generate-test-resources
process-test-resources
test-compile
process-test-classes
test
prepare-package
package
pre-integration-test
integration-test
post-integration-test
verify
install
deploy
clean
包含以下phase:
pre-clean
clean (注意这个clean不是lifecycle而是phase)
post-clean
大多数phase在执行过程中,因为我们通常没有在pom.xml中配置相关的设置,所以这些phase什么事情都不做。
(2) phase 下的 goal
执行的Phase | 对应执行的Goal |
---|---|
compile | compiler:testCompile |
test | compiler:compile surefire:test |
3 执行
(1) 语法
[常用] 方法一 指定到phase:
1 指定一个phase
如:
mvn package
从default生命周期开始一直运行到package这个phasemvn compile
从default生命周期开始一直运行到compile这个phase
用mvn这个命令时,后面的参数是phase,Maven自动根据生命周期运行到指定的phase。
2 指定多个phase
如:
mvn clean package
Maven先执行clean生命周期并运行到clean这个phase,然后执行default生命周期并运行到package这个phase
[不常用] 方法二 指定到goal:
mvn tomcat:run
启动Tomcat服务器
(2) 常用的
1 常用的phase
- clean:清理
- compile:编译
- test:运行测试
- package:打包
2 常用的命令
mvn clean
:清理所有生成的class和jar;mvn clean compile
:先清理,再执行到compile;mvn clean test
:先清理,再执行到test,因为执行test前必须执行compile,所以这里不必指定compile;mvn clean package
:先清理,再执行到package。
4 插件
(1) 介绍
实际上,执行每个phase,(背后)都是通过某个插件(plugin)来执行的,Maven本身其实并不知道如何执行compile,它只是负责找到对应的compiler插件,然后执行默认的goal来完成编译。
比如执行 mvn compile
等于 执行到 compiler:compile 这个goal.
(2) 插件分类
标准插件
Maven已经内置了一些常用的标准插件:
插件名称 | 对应执行的phase |
---|---|
clean | clean |
compiler | compile |
surefire | test |
jar | package |
自定义插件
标准插件无法满足需求,我们还可以使用自定义插件。
1 常用自定义插件
- maven-shade-plugin:打包所有依赖包并生成可执行jar;
- cobertura-maven-plugin:生成单元测试覆盖率报告;
- findbugs-maven-plugin:对Java源码进行静态分析以找出潜在问题。
2 怎么配置?
打开 pom.xml:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
... //
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
插入如下面的代码
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.itranswarp.learnjava.Main</mainClass>
</transformer>
</transformers>
</configuration>
5 模块
(1) 介绍
Maven可以有效地管理多个模块,我们只需要把每个模块当作一个独立的Maven项目,它们有各自独立的pom.xml
(2) 如何分拆
1 每个模块里都来个pom.xml
2 重复的pom.xml可以提出公共的pom.xml -- 继承
若模块A和模块B的pom.xml高度相似,我们可以提取出共同部分作为parent
:
注意parent的pom.xml里的
是pom而不是jar,因为parent本身不含任何Java代码。
3 最后根目录再来一个全局统领的 pom.xml
然后通过<modules>
把分散各处的 pom.xml 衔接起来
具体看https://www.liaoxuefeng.com/wiki/1252599548343744/1309301243117601
这样,(比如)在根目录执行mvn clean package
时,Maven根据根目录的pom.xml找到包括parent在内的共4个
6 mvnw
默认情况下,系统所有项目都会使用全局安装的这个Maven版本。
Maven Wrapper就是给一个项目提供一个独立的,指定版本的Maven给它使用。
7 发布Artifact
(1) 目的
当我们自己写了一个牛逼的开源库时,非常希望别人也能使用,总不能直接放个jar包的链接让别人下载吧?
(2) 方法
以静态文件发布
通过GitHub Pages发布Maven repo
注意: 通过静态文件的方式发布repo,实际上我们是可以修改jar文件的,但最好遵守规范,不要修改已发布版本。
通过Nexus发布到中央仓库
但我们不能直接发布到Maven中央仓库,而是通过曲线救国的方式,发布到central.sonatype.org
,它会定期自动同步到Maven的中央仓库
此方法前期需要复杂的申请账号和项目的流程,后期需要安装调试GPG,但只要跑通流程,后续发布都只需要一行命令。
发布到私有仓库
- 1 公司内部自己搭建的
Nexus服务器
。 - 2 如果没有私有Nexus服务器,还可以发布到
GitHub Packages
。GitHub Packages是GitHub提供的仓库服务,支持Maven、NPM、Docker等。