一、Maven概念
1.1 Maven简介
Maven是一个项目管理工具,它包含了一个项目对象模型(Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。当你使用 Maven 的时候,你用一个明确定义的项目对象模型来描述你的项目,然后 Maven 可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。
Maven翻译为“专家”,“内行”。Maven是 Apache 下的一个纯 Java 开发的开源项目,它是一个项目管理工具,可以使用 Maven 对 Java 项目进行构建、依赖管理。当前使用 Maven 的项目在持续增长。
Maven官网:https://maven.apache.org/
Maven功能:清理、编译、测试(自己写单元测试)、报告、打包(导出jar、war)、部署。
1.2 什么是项目构建
项目构建是一个项目从编写源代码到编译、测试、打包、部署、运行的过程。
1.2.1 传统项目构建过程
传统的使用Eclipse构建项目的过程如下:
构建过程如下:
1、在Eclipse中创建一个JavaWeb工程。
2、在工程中编写源代码及配置文件等。
3、对源代码进行编译,Java文件编译成class文件。
4、执行Junit单元测试。
5、将工程打成war包部署至Tomcat运行。
1.2.2 Maven项目构建过程
Maven将项目构建的过程进行标准化,每个阶段使用一个命令完成,下图展示了构建过程的一些阶段,后面章节详细介绍每个阶段,这里先大概了解下:
上图中部分阶段对应命令如下:
清理阶段对应的 Maven 命令是clean,清理输出的class文件。
编译阶段对应的 Maven 命令是compile,将Java代码编译成class文件。
打包阶段对应的 Maven 命令是package,Java工程可以打成jar包,web工程可以打成war包。
运行一个Maven工程(web工程)需要一个命令:tomcat:run。
Maven工程构建的优点:
1、一个命令完成构建、运行,方便快捷。
2、Maven对每个构建阶段进行规范,非常有利于大型团队协作开发。
1.3 什么是依赖管理
什么是依赖? 一个Java项目可能要使用一些第三方的jar包才可以运行,那么我们说这个Java项目依赖了这些第三方的jar包。举个例子:一个crm系统,它的架构是SSH框架,该crm项目依赖SSH框架,具体它依赖Hibernate、Spring、Struts2相关jar包。
什么是依赖管理? 就是对项目所有依赖的jar包进行规范化管理。
1.3.1 传统项目的依赖管理
传统的项目工程要管理所依赖的jar包完全靠人工进行,程序员从网上下载jar包添加到项目工程中,如下图:程序员手工将Hibernate、Struts2、Spring的jar添加到工程中的WEB-INF/lib目录下。
手工拷贝jar包添加到工程中的问题是:
1、没有对jar包的版本统一管理,容易导致版本冲突。
2、从网上找jar包非常不方便,有些jar找不到。
3、jar包添加到工程中导致工程过大。
1.3.2 Maven项目的依赖管理
Maven项目管理所依赖的jar包不需要手动向工程添加jar包,只需要在pom.xml(Maven工程的配置文件)添加jar包的坐标,自动从Maven仓库中下载jar包、运行,如下图:
使用Maven依赖管理添加jar的好处:
1、通过pom.xml文件对jar包的版本进行统一管理,可避免版本冲突。
2、Maven团队维护了一个非常全的Maven仓库,里边包括了当前使用的jar包,Maven工程可以自动从Maven仓库下载jar包,非常方便。
1.4 Maven概念模型
在上述概念中,我们提到:Maven 是一个项目管理工具,它包含了一个项目对象模型(Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。
1.4.1 项目对象模型(Project Object Model)
Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件。
Maven除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较高的可重用性,所以常常用两三行 Maven 构建脚本就可以构建简单的项目。
一个Maven工程都有一个pom.xml文件,通过pom.xml文件定义项目的坐标、项目依赖、项目信息、插件目标等。
我们先看一下pom.xml:
<?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>
<groupId>com.maven</groupId>
<artifactId>maven-helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>第一个maven工程</name>
<description>第一个maven工程</description>
<!-- 添加依赖: servlet-api,jsp-api,junit单元测试 -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<!-- 配置了很多插件 -->
<plugins>
<!--jdk编译插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<!--引入tomcat7的插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<!--端口号-->
<port>9090</port>
<!--path就相当于部署项目时候的ContextPath-->
<path>/mgr</path>
<uriEncoding>UTF-8</uriEncoding>
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
</build>
</project>
第一部分:工程的基本信息
<modelVersion>4.0.0</modelVersion>
<groupId>com.maven</groupId>
<artifactId>maven-helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>第一个maven工程</name>
<description>第一个maven工程</description>
第二部分:被dependencies包围起来的是项目中需要用到的jar包
<!-- 添加依赖: servlet-api,jsp-api,junit单元测试 -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
第三部分:被build包围起来的是项目中需要用到的插件
<build>
<!-- 配置了很多插件 -->
<plugins>
<!--jdk编译插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<!--引入tomcat7的插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<!--端口号-->
<port>9090</port>
<!--path就相当于部署项目时候的ContextPath-->
<path>/mgr</path>
<uriEncoding>UTF-8</uriEncoding>
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
</build>
在上面已经详细介绍了,分为三个部分,分别为:
1、项目自身信息。
2、项目运行所依赖的jar包信息。
3、项目运行环境信息,比如:jdk、tomcat信息。
1.4.2 依赖管理系统(Dependency Management System)
通过Maven的依赖管理对项目所依赖的jar包进行统一管理。项目通过在pom.xml中定义依赖来管理jar包。
图片上的 central 是指中央仓库,b2b 是指远程仓库,local 是指本地仓库,这里着重介绍组成Dependency的三大部分:
1、公司组织的名称。
2、项目名。
3、版本号。
下面分析一个具体的Dependency:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
其中 javax.servlet 为公司组织(父项目)的名称,javax.servlet-api 为项目名,3.0.1 为版本号。
为什么要进行依赖管理?
依赖管理:
1、可连接互联网来自动下载。
2、对我们自己开发的模块做依赖管理。
1.4.3 项目生命周期(Project Lifecycle)
图片下半部分的 Build lifecycle 是指 Maven 的生命周期,下面的Plug-in是指插件,即每一个Maven的命令都对应着Maven的底层插件。
通过Maven完成项目的构建:清理、编译、测试、部署等,Maven将这些工程规范为一个生命周期。
Maven通过执行一些简单命令就可以实现上面生命周期各个过程。
1.4.4 一组标准集合
Maven将整个项目管理过程定义一组标准,比如Maven构建工程有标准的目录结构,有标准的生命周期阶段,依赖管理有标准的坐标定义等。
Maven提倡使用一个共同的标准目录结构,方便不同开发者的协作,也方便了一些统一的自动化脚本的实现。
以前创建的java项目:
src -> 源码目录,但这不是标准,我们可以随便创建一个文件夹,让其成为源码目录。
libs -> 第三方jar包,但是该目录可以是任意的名称。
以前创建的web项目:
src -> 源码目录。
web -> 通过IDEA工具创建的,用来存放静态资源、配置文件、第三方jar的目录。
WebContent/WebRoot -> 通过Eclipse工具创建的,用来存放静态资源、配置文件、第三方jar的目录。
我们之前创建的项目,不存在标准。
1.4.5 插件目标
Maven管理项目生命周期是基于插件完成的。
1.5 为什么使用Maven
1、一个项目就是一个工程
如果项目非常庞大,就不适合使用package来划分模块,最好是每一个模块对应一个工程,利于分工协作。借助于Maven就可以将一个项目拆分成多个工程。
2、项目中使用jar包,需要“复制”、“粘贴”项目的lib中,不方便管理
当我们的项目比较大的时候,我们会将一个大的项目分成很多小的项目,每个小项目由几个开发负责,比如一个电商项目分为:账户相关的项目、订单相关的项目、商品相关的项目,这些项目的结构都是类似的,用到的技术都是一样的:SSM(Spring、Springmvc、Mybatis),然后每个项目都需要把这些jar拷贝一份到自己的项目目录中,最后10个项目只是jar就复制了10份,后来,我们发现项目中有些jar需要升级版本,打算替换一下,此时我们需要依次去替换10个项目,也是相当痛苦。
借助于Maven,可以将jar包保存在“仓库”中,不管在哪个项目只要使用引用即可就行。
3、jar包需要的时候每次都要自己准备好或到官网下载
比如我们项目中需要用到fastjson,此时我们会去百度上检索fastjson相关jar包,然后下载下来,放到项目的lib下面,然后加到项目的classpath下面,用着用着发现这个jar的版本太老了,不是我们想要的,然后又重新去找,痛苦啊。
Maven给每个jar定义了唯一的标志,这个在maven中叫做项目的坐标,通过这个坐标可以找到你需要用到的任何版本的jar包。
4、jar包版本不一致的风险
项目中用到了a.jar,a.jar依赖于c.jar的1.5版本,然后我们把这2个jar拷贝到项目中,后面又用到了b.jar,但是b.jar又依赖于c.jar的1.0版本,此时你把b.jar和c-1.0.jar引进来了,会发现c.jar有2个版本,发生冲突了,启动的时候会报错,这种情况你要着手去解决jar冲突的问题,也是非常痛苦的。
Maven可以很容易的解决不同版本之间的jar冲突的问题。
5、一个jar包依赖其他的jar包需要自己手动的加入到项目中
jar包一般都不是独立存在的,一般一些jar也会用到其他的jar,比如spring-aop.jar会用到spring-core.jar,这种依赖可能比较简单,有些依赖可能有很多级,比如a.jar依赖于b.jar,而b.jar依赖c.jar,而c.jar又依赖于d.jar,当你用到a.jar的时候,你需要把其他3个也进入才可以,所以你用到一个jar的时候,你必须明确知道这些jar还会依赖于哪些jar,把他们都引入进来,否则项目是无法正常运行的,当项目用到很多jar的时候,我们是很难判断缺少哪些jar的,只有在项目运行过程报错了,才知道,这种也是相当痛苦的,浪费了大量时间。
Maven会自动解决jar依赖的问题,比如你用到了a-1.0.jar,而a-1.0.jar依赖于b-1.1.jar和c-1.5.jar,当我们通过Maven把a-1.0.jar引入之后,b-1.1.jar和c-1.5.jar会自动被引入进来。
6、统一的项目结构
很久之前,我们使用eclipse搭建一个项目的时候,Java源码的位置、资源文件的位置、测试文件的位置、静态资源位置、编译之后的class文件位置,都是可以随意放的,这些是由各自公司的架构师搭建项目时定好的,根据他们的经验来定义的,导致每个公司可能项目结构都不太一样,来新人之后,看到项目结构一脸闷逼,根本不知道哪是哪,需要人指导,无形的增加了成本,如果大家都按照某种规范采用同一种项目结构,这样岂不是很方便么,大家按照某种约定,项目使用同样的结构,比如:Java文件、资源文件、测试用例、静态资源、编译之后的class、打包之后jar的位置等等各种文件的位置,这些东西,如果所有做Java开发的公司都约定好的,这样拿到一个项目之后,就可以省去很多事情了。
使用Maven搭建的项目架构,都需要遵循同样的结构,Java源文件、资源文件、测试用例类文件、静态资源文件这些都是约定好的,大家都按照这个约定来,所有如果你们的项目是使用Maven创建的,招新人来接手,如果他们懂Maven,根本不需要培训,上来就可以看懂整个项目的结构。
7、跨平台
Maven的跨平台,可在Window、Linux上使用。
二、Maven安装与配置
2.1 安装JDK,并配置JDK的环境变量
Maven的安装必须基于JAVA_HOME配置的环境变量。
系统变量:
变量名:JAVA_HOME
变量值:JDK安装根路径 (C:\Java\jdk1.8.0_311)
Path路径引入:
%JAVA_HOME%\bin
注:Maven3.3+版本,jdk至少是1.7及以上版本
2.2 Maven安装
2.2.1 Maven下载
Maven的官网下载地址:https://maven.apache.org/download.cgi,可以下载最新版本。
注:Maven无需要求最新版,但至少3.3+版本。
2.2.2 Maven安装
Maven本身是绿色版不需要安装,解压即可。将Maven解压到一个不含有中文和空格的目录中。
2.2.3 配置Maven环境变量
1、计算机右键 -> 属性 -> 高级系统设置 -> 高级选项卡 -> 环境变量。
2、新建系统变量:
变量名:MAVEN_HOME
变量值:D:\Tools\apache-maven-3.8.5(Maven解压路径)
3、在Path系统变量中加入%MAVEN_HOME%\bin
2.2.4 测试
打开cmd命令行窗口,通过mvn -version命令测试配置是否成功。
2.3 Maven目录分析
bin目录:Maven运行的脚本。
mvn(以run方式运行项目)
mvnDebug(以debug方式运行项目)
boot目录:Maven运行需要的类加载器。
conf目录:
settings.xml,整个Maven工具核心配置文件。
lib目录:Maven运行依赖jar包。
2.4 全局settings与用户settings
Maven仓库地址、私服等配置信息需要在settings.xml文件中配置,分为全局配置和用户配置。
在Maven安装目录下的有 conf/settings.xml文件,此settings.xml文件用于Maven的所有project项目,它作为Maven的全局配置。
如需要个性配置则需要在用户配置中设置,用户配置的setting.xml文件默认的位置在:${user.home}/.m2/settings.xml目录中,${user.home} 指 windows 中的用户目录。(个人推荐)
Maven会先找用户配置,如果找到则以用户配置文件为准,否则使用全局配置文件。
作用:Maven的本地仓库位置,中央仓库镜像等配置。
maven全局配置文件settings.xml详解:https://cloud.tencent.com/developer/article/1014577
2.5 配置阿里云镜像仓库
所有使用Maven构建的项目,都会去Maven仓库下载,会出现两个问题:
1、下载速度过慢。
2、官方镜像节点黑名单机制。
注意:查看对外访问的ip地址ip138.com。
基于以上问题,我们需要配置国内的镜像节点,推荐使用阿里云镜像(记得注释掉默认的镜像节点)。
注:“镜像(Mirroring)是一种文件存储形式,是冗余的一种类型,一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本即为镜像。”
方式一:全局配置
可以添加阿里云的镜像到maven的setting.xml配置中,这样就不需要每次在pom中,添加镜像仓库的配置,在mirrors节点下面添加子节点:
<mirrors>
<!-- mirror
| Specifies a repository mirror site to use instead of a given repository. The repository that
| this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
| for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
|
<mirror>
<id>mirrorId</id>
<mirrorOf>repositoryId</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://my.repository.com/repo/path</url>
</mirror>
-->
<!--
<mirror>
<id>maven-default-http-blocker</id>
<mirrorOf>external:http:*</mirrorOf>
<name>Pseudo repository to mirror external repositories initially using HTTP.</name>
<url>http://0.0.0.0/</url>
<blocked>true</blocked>
</mirror>
-->
<!-- 配置阿里云镜像节点 -->
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
方式二:用户配置
把conf/settings.xml复制一份到.m2文件夹下面。
注:如果创建.m2文件夹失败,可以考虑使用命令行来创建,进入到用户目录,执行mkdir .m2。
注:一定要把镜像配置放到<mirrors>
下面
2.6 Maven卸载
Maven由于安装的时候只是解压,配置环境变量,设置本地仓库,所以卸载的时候也很简单。
1、删除解压的maven文件夹;
2、删除设置的环境变量MAVEN_HOME,删除path里添加的“%MAVEN_HOME%\bin;”;
3、删除本地仓库;