一、Maven坐标和仓库
Maven坐标是一个唯一的标识,用于表示我们的项目的一些信息或者引用jar包的位置。而这些唯一标识指向的地方就是maven仓库,仓库就是用来统一存储所有Maven共享构建的位置。
Maven仓库的分类:
- 本地仓库:
在Maven的settings.xml文件中进行配置:<localRepository>本地仓库的路径</localRepository>
每个用户只能有一个本地仓库 - 远程仓库:
中央仓库:Maven默认的远程仓库
地址:http://repo1.maven.org/maven2
私服:是一种特殊的远程仓库,它是架设在局域网内的仓库,我们在上一节中配置Maven的settings.xml文件时,就设置了阿里云的私服。
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
Maven坐标的构成:
GroupId:定义当前Maven项目隶属的项目
ArtifactId:定义实际项目中的一个模块
version:定义当前项目的当前版本
packaging:定义该项目的打包方式(如果坐标表示应用jar包的位置,则没有这个属性)
Maven坐标的作用:
Maven世界有大量的构建,我们需要找一个用来唯一标识一个构建的统一规范,用了统一的规范,我们就可以把查找的工作交给机器。
Maven中jar包的引用方法:
我们可以在http://mvnrepository.com/中查找我们需要的jar包坐标。
然后找到我们需要的版本,将该版本的jar包加入到项目的pom.xml文件中去。
保存后我们可以发现,我们的项目中出现了这个jar包
二、Maven的依赖管理与依赖规范
1、依赖范围
在Maven中我们可以通过设置依赖范围控制依赖和编译、测试、运行的classpath的关系,主要有四种依赖关系:
- compile:默认编译依赖范围。对于编译、测试、运行的三种classpath都有效。
- test:测试依赖范围,只对于测试classpath有效。
- provided:已提供依赖范围。对于编译、测试的classpath都有效,但对于运行无效。
-
runtime:测试和运行时提供。
2、依赖范围的使用
在之前的学习中,我们使用不同包中的类可以通过导包的方法实现,但是不能在不同的项目中相互调用类或者方法。现在我想在项目A中调用项目B中的方法,我们可以通过将项目B打包成一个jar包,然后导入到项目A中去,这样,项目A就可以使用项目B的方法了。
现在,我们创建两个java项目进行测试。
首先在mavenJava01中创建一个Time类,在这个类中写一个获取当前时间毫秒值的方法。
package com.itheima.mavenJava01;
public class Time {
//获取当前系统时间的毫秒值
public long getCurrentTime(){
long time = System.currentTimeMillis();
return time;
}
}
然后我们将mavenJava01项目的pom.xml文件中的坐标复制到mavenJava02项目的pom.xml文件中去,我们可以发现,mavenJava02项目Maven Dependencied中出现了mavenJava02项目,这样我们可以说mavenJava02项目依赖于mavenJava01项目。
在mavenJava02项目中创建一个类,调用Time类中的方法,控制台输出了当前时间的毫秒值。
package mavenJava02;
import com.itheima.mavenJava01.Time;
public class PrintTime {
public static void main(String[] args) {
Time time = new Time();
System.out.println(time.getCurrentTime());
}
}
由于maven中的Java项目默认的依赖范围是compile,我们的mavenJava02项目依赖于mavenJava01项目,也就可以使用mavenJava01项目中的类和方法。如果我们修改mavenJava01项目pom.xml文件中的依赖范围,mavenJava02项目就可能不能调用mavenJava01项目中的类和方法。
3、直接依赖和间接依赖
我们使用一个例子来说明直接依赖和间接依赖。我们现在有两个项目,分别是项目1和项目2,项目1的pom.xml文件中我们引入了junit的jar包,然后我们又在项目2的pom.xml文件中加入了项目1的坐标。
- 项目1:
pom.xml:junit - 项目2:
pom.xml:加入项目1的坐标
这样我们可以说:
(1)junit是项目1的直接依赖
(2)项目1是项目2的直接依赖
(3)junit是项目2的间接依赖
这也被称为传递性依赖。传递性依赖的影响范围如下图所示:
图中的第四行第四列应该是不能进行传递。
我们在项目中进行实现:
首先在mavenJava01项目pom.xml文件中引入junit的jar包,影响范围是test。
然后我们还在mavenJava02项目pom.xml文件中放入mavenJava01项目的坐标,但是我们发现Maven Despendencies中没有导入junit的jar包。如果我们将mavenJava01项目中的junit的jar包依赖范围改为compile,我们就会发现Maven Despendencies中出现了junit的jar包。
4、依赖控制和依赖排除
依赖控制:控制自己的依赖的包是否向下传递
依赖排除:可以排除掉某些我们不需要的jar包
我们来进行测试:
首先我们在mavenJava01项目中对junit的jar包设置依赖控制,我们发现mavenJava02项目中Maven Despendencies中没有了junit的jar包。
然后我们去掉依赖控制,在mavenJava02项目中设置依赖排除,我们也可以发现mavenJava02项目中Maven Despendencies中没有junit的jar包。
三、Maven的生命周期
Maven的生命周期是为了对所有的构建过程进行抽象和统一,包括项目清理、初始化、编译、打包、测试、部署等几乎所有构建步骤。
Maven的三大生命周期:
- Clean Lifecycle:清理项目的生命周期,在进行真正的构建之前进行一些清理工作。
- Default Lifecycle:构建项目的生命周期,用于构建的核心部分,编译、测试、打包、部署等等。
- Site Lifecycle:生成项目站点的生命周期,用于生成项目报告、站点,发布站点。
注意:Maven的三大生命周期是相互独立的,在只调用clean清理工作目录的时候,site和default都不会执行;但是可以使用命令同时执行三套生命周期。
1、clean生命周期
clean生命周期分为三个阶段:
- pre-clean:执行一些需要在clean之前完成的工作
- clean:移除所有上一次构建生成的文件
- post-clean:执行一些需要在clean之后立刻完成的工作
由于mvn命令指向的是生命周期的阶段,所以mvn clean指向的就是clean阶段,但是需要注意的是,运行某个阶段的时候,这个阶段之前的阶段都会被运行,我们再执行mvn clean的时候,pre-clean和clean阶段都会被运行。这是Maven很重要的一个规则,可以大大简化命令行的输入。
2、site生命周期
site生命周期分为四个阶段:
- pre-site:执行一些需要在生成站点文档之前完成的工作
- site:生成项目的站点文档
- post-site:执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
- site-deploy:将生成的站点文档部署到特定的服务器上
这里常用的是site阶段和site-deploy阶段,用以生成和发布Maven站点,这是Maven非常强大的功能,可以自动生成文档和统计数据。
3、default生命周期
default生命周期是Maven生命周期中最重要的一个,绝大部分工作都发生在这个生命周期中,我们在这里只解释一些比较重要和常用的阶段:
- process-resources:复制并处理资源文件至目标目录,准备打包
- compile:编译项目的源代码
- process-test-resources:复制并处理资源文件至目标测试目录
- test-compile:编译测试源代码
- test:使用合适的单元测试框架进行测试。这些测试代码不会被打包或部署
- package:接受编译好的代码,打包成可发布的格式
- install:将包安装至本地仓库,以让其他项目依赖
- deploy:将最终的包复制到远程的仓库,以让其他开发人员与项目共享
四、Maven的插件
Maven实际上相当于一个骨架,是抽象的东西,没有做具体的事情,要想做一些事情就需要加入插件,这些插件的运行同时也依赖着Maven的生命周期,需要在那个Maven生命周期去执行插件,去执行插件的那个功能,都需要在配置文件中进行配置。下面介绍一些常用的插件:
1、指定源码的jdk版本
由于maven的默认编译使用的jdk版本很低,使用maven-compiler-plugin插件可以指定项目源码的jdk版本,编译后的jdk版本,以及编码,在source标签和target标签中设置jdk的版本。
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
2、tomcat插件
用于配置tomcat的路径和端口号
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
<port>8080</port>
</configuration>
</plugin>
</plugins>
</build>
3、打包源码插件
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
标签phase中配置的是什么时候执行插件,上面的属性package就是指在运行mvn package的时候执行插件。
标签goal中配置的是执行查件的那个功能,上面的属性jar-no-fork就是要执行插件的jar-no-fork功能。