maven是什么?
Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。 当你使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后 Maven 可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。
maven采用**约定优于配置(Convention Over Configuration)**理念,比如源码、单元测试、class文件等存放的目录都采用约定目录。
在没有自定义的情况下,源代码假定是在src/main/java,资源文件假定是在src/main/resources。测试代码假定是在src/test 。项目假定会产生一个 JAR 文件。Maven假定你想要把编译好的字节码放到target/classes 并且在target 创建一个可分发的 JAR 文件
安装maven
maven是基于java实现的,因此依赖本机安装java,推荐安装maven3.X版本,jdk一般需要1.8+版本。
安装比较简单,安装完jdk之后从官网http://maven.apache.org/download.html.下载maven二进制包安装即可。
安装完成之后命令行执行mvn -v能正常输出类似返回即可
配置maven
maven的依赖下载顺序是先访问本地仓库,若有则直接使用。若本地仓库没有会从私服/私库下载,仍下载不到会从远程/共享仓库下载。
默认的远程仓库为http://repo1.maven.org/maven2/,由于墙的原因一般下载会很慢,可以通过mirror的方式替换。
公司有自建的nexus做私服的话可以配置私服为依赖包下载的地址,避免了从公网下载以便加快下载速度。
一份示例的maven的setting文件,在maven安装目录的conf/settings.xml
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<!-- 本地仓库路径 -->
<localRepository>C:\Program Files\apache-maven-3.6.3-bin\repo</localRepository>
<!-- 一般无需添加,留空即可 -->
<pluginGroups>
<pluginGroup>org.jenkins-ci.tools</pluginGroup>
</pluginGroups>
<!-- <proxies>
<proxy>
<id>myproxy</id>
<active>true</active>
<protocol>http</protocol>
<host>proxy.somewhere.com</host>
<port>8080</port>
<username>proxyuser</username>
<password>somepassword</password>
<nonProxyHosts>*.google.com|ibiblio.org</nonProxyHosts>
</proxy> -->
</proxies>
<servers>
<!-- 需要本地上传包到私服才需要配置 -->
</servers>
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<!--国内的代理仓库,避免去中央仓库下载,加快速度 -->
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<!-- 被镜像的服务器的id。如果要设置一个Maven中央仓库(http://
repo1.maven.org/maven2)的镜像,就需要将该元素设置成central-->
<mirrorOf>central</mirrorOf>
</mirror>
<mirror>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
<mirrorOf>m.g.o-public</mirrorOf>
</mirror>
</mirrors>
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
<profile>
<id>nexus</id>
<!-- 远程仓库列表 -->
<repositories>
<repository>
<id>nexus</id>
<name>nexus</name>
<!-- 虚拟的URL形式,指向镜像的URL-->
<!-- 替换成具体私服地址 -->
<url>http://xxx.xxx.xxx.xxx/repository/maven-public/</url>
<layout>default</layout>
<!-- 表示可以从这个仓库下载releases版本的构件-->
<releases>
<enabled>true</enabled>
</releases>
<!-- 表示可以从这个仓库下载snapshot版本的构件 -->
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<!-- 插件仓库列表 -->
<pluginRepositories>
<pluginRepository>
<id>nexus</id>
<name>nexus</name>
<!-- 替换成具体私服地址 -->
<url>http://xxx.xxx.xxx.xxx/repository/maven-public/</url>
<layout>default</layout>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
</profile>
<!-- Give access to Jenkins plugins -->
<profile>
<id>jenkins</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<!-- 声明哪些profile是激活的 -->
<activeProfile>nexus</activeProfile>
<activeProfile>jdk-1.8</activeProfile>
<activeProfile>jenkins</activeProfile>
</activeProfiles>
</settings>
maven核心概念
maven生命周期
本小节整理参考地址
每个项目都要进行清理、编译、测试、打包以及安装部署,这些就是生命周期。构建生命周期具体步骤包括清理、初始化、编译、测试、打包、集成测试、验证、部署和生成站点。这些步骤几乎适合所有的项目,也就是说,所有项目的管理构建过程都可以对应到这个生命周期上来。
maven根据实际情况抽象提炼出来的一个统一标准和规范作为生命周期,但maven是不做具体事情的,而是由一个个插件来实现的。 在项目的构建过程中,只是在方向和步骤上面起到了管理和协调的作用。
Maven 拥有三套独立的生命周期,它们分别是 clean、default 和 site(不常用)。clean 生命周期的目的是清理项目;default 生命周期的目的是构建项目;site 生命周期的目的是建立项目站点。
每个生命周期又包含了多个阶段。这些阶段在执行的时候是有固定顺序的。后面的阶段一定要等前面的阶段执行完成后才能被执行。
比如 clean 生命周期,它就包含 pre-clean、clean 和 post-clean 三个阶段。用户调用 pre-clean 时,只有 pre-clean 阶段被执行;调用 clean 时,先执行 pre-clean,再执行 clean 阶段;同理,当调用 post-clean 时,Maven 自动先执行 pre-clean、再执行 clean,最后执行 post-clean。
1. clean 生命周期
clean 生命周期的目的是清理项目,它包括以下三个阶段。 但是一般执行命令是mvn clean,不需要关心三个阶段的先后顺序,知道它会清理项目编译的target目录即可
- pre-clean:执行清理前需要完成的工作。
- clean:清理上一次构建过程中生成的文件,比如编译后的 class 文件等。
- post-clean:执行清理后需要完成的工作。
2. default 生命周期
default 生命周期定义了构建项目时所需要的执行步骤,它是所有生命周期中最核心部分,比较常用的阶段如下 - compile 编译项目中的源代码
- test-compile 编译测试代码
- test 运行测试案例
- package 将编译后的 class 和资源打包成压缩文件,比如 rar
- verify 检测测试后的包是否完好
- install 将打包的组件以构件的形式,安装到本地依赖仓库中
- deploy 运行集成和发布环境,将测试后的最终包以构件的方式发布到远程仓库中,方便所有程序员共享
各阶段的详细介绍内容可以参考链接:
http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
3. site 生命周期(不常用,看下即可)
site 生命周期的目的是建立和发布项目站点。Maven 可以基于 pom 所描述的信息自动生成项目的站点,同时还可以根据需要生成相关的报告文档集成在站点中,方便团队交流和发布项目信息。site 生命周期包括如下阶段。
pre-site:执行生成站点前的准备工作。
site:生成站点文档。
post-site:执行生成站点后需要收尾的工作。
site-deploy:将生成的站点发布到服务器上。
maven坐标
Maven通过坐标来精确定位一个项目。maven通过groupId:artifactId:packaging:version来唯一定义一个项目对象模型(POM)
- groupId:公司,组织的标识,约定是,它以创建这个项目的组织名称的逆向域名(reverse domain name)开头。来自Sonatype的项目有一个以com.sonatype开头的groupId
- artifactId:在groupId下的表示一个单独项目的唯一标识符
- version:一个项目的特定版本
- packaging:项目的类型,默认是jar,还有pom类型
创建简单的maven项目
创建项目
可以用原始的 mvn archetype:create创建骨架项目,也可以用idea或eclipse在界面创建。推荐用idea创建,创建项目,选择项目类型
输入项目名,就会在后台创建(默认会从中央仓库下载,比较慢)
#执行项目编译
mvn clean compile
添加依赖
在项目的dependencies中新增一个依赖
依赖具体坐标可以在maven终于仓库搜索https://mvnrepository.com/,根据实际情况选择
多模块maven项目,默认的maven项目只有一个module,在实际工作中通常会将项目按功能或实现方式拆分成几个子模块,由根目录下的pom.xml统一管理,但是管理上还是以一个仓库的维度,比如各子模块都依赖的公共依赖,就放在父模块中,各子模块只需在parent的依赖的基础上再添加自定义依赖
依赖管理 (Dependency Management)
maven的依赖是传递的,比如你依赖了spring的某个包,不需要关心它的依赖,maven编译打包时会自动下载。项目A依赖于项目B和C,项目B依赖于项目D,项目C依赖于项目E,但是项目A所需要做的只是定义对B和C的依赖。
maven也提供了不同的依赖范围(dependency scope)。比如项目的pom.xml包含了一个依赖junit:junit:jar:4.12其范围是test。当一个依赖的范围是test的时候,说明它在Compiler插件运行compile目标的时候是不可用的。它只有在运行compiler:testCompile和surefire:test目标的时候才会被加入到classpath中。
对应上面的多模块项目,当需要由父项目指定依赖的插件和版本时,通过dependencyManagement来实现,这样子模块依赖由dependencyManagement声明的依赖时,版本号只能是parent里的dependencyManagement声明的组件版本
可以通过 mvn dependency:tree命令查看当前项目的依赖树