Maven第六讲
项目pom.xml中,有下面这样一段依赖:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
</dependencies>
大家看一下上面的配置,有没有什么问题?
他们的groupId和version都是一样的,程序员面对与重复的代码,需要提取,如果是java代码中,我们可以将同样的代码或者变量值,提取成方法或者变量,做到重用,方便维护。
那么maven的pom.xml中也支持这么做:
<properties>
<spring.group>org.springframework</spring.group>
<spring.version>5.2.1.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>${spring.group}</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>${spring.group}</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>${spring.group}</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
大家看一下上面的代码,properties位于pom.xml中的,是project元素的子元素,用户可以在properties中自定义一些用户属性,然后可以在其他地方使用${属性名称}这种方式进行引用。
生命周期
我们开发一个项目的时候,通常有这些环节:创建项目、编写代码、清理已编译的代码、编译代码、执行单元测试、打包、集成测试、验证、部署、生成站点等,这些环节组成了项目的生命周期,这些过程也叫做项目的构建过程,几乎所有的项目都由这些环节中的其中几个,创建项目和编写代码是我们程序员需要多参与的,其他的都可以做成自动化的方式。
用过ant的朋友回忆一下,在maven出现以前,开发人员每天都在对项目进行清理、编译、执行单元测试、打包、部署等操作,虽然大家都在做这些工作,但是没有一个统一的标准,项目和项目之间,公司和公司之间,大多数都是各写各的,写法是千奇百怪,能满足自身需求就可以了,但是换个项目就得从头再来,这些操作又需要重新编写脚本。
而maven出来之后,项目生命周期中的这些环节都被简化了,被规范化了,maven出现之前,项目的结构没有一个统一的标准,所以生命周期中各个环节对应的自动化脚本也是各种各样,而maven约定好了项目的结构,源码的位置、资源文件的位置、测试代码的位置、测试用到的资源文件的位置、静态资源的位置、打包之后文件的位置等,这些都是maven约定好的,所以清理代码用一个命令mvn clean就可以完成,不需要我们去配置清理的目标目录;用mvn compile命令就可以完成编译的操作;用mvn test就可以自动运行测试用例;用mvn package就可以将项目打包为jar、war格式的包,能够如此简单,主要还是maven中约定大于配置的结果。
maven中生命周期详解
maven将项目的生命周期抽象成了3套生命周期,每套生命周期又包含多个阶段,每套中具体包含哪些阶段是maven已经约定好的,但是每个阶段具体需要做什么,是用户可以自己指定的。
maven中定义的3套生命周期:
-
clean生命周期
-
default生命周期
-
site生命周期
上面这3套生命周期是相互独立的,没有依赖关系的,而每套生命周期中有多个阶段,每套中的多个阶段是有先后顺序的,并且后面的阶段依赖于前面的阶段,而用户可以直接使用mvn命令来调用这些阶段去完成项目生命周期中具体的操作,命令是:
mvn 生命周期阶段
通俗点解释:
maven中的3套生命周期相当于maven定义了3个类来解决项目生命周期中需要的各种操作,每个类中有多个方法,这些方法就是指具体的阶段,方法名称就是阶段的名称,每个类的方法是有顺序的,当执行某个方法的时候,这个方法前面的方法也会执行。具体每个方法中需要执行什么,这个是通过插件的方式让用户去配置的,所以非常灵活。
用户执行mvn 阶段名称就相当于调用了具体的某个方法。
下面我们来看看每个生命周期中有哪些阶段(也就是我们说的每个类中有哪些方法,顺序是什么样的)。
clean生命周期
clean生命周期的目的是清理项目,它包含三个阶段:
生命周期阶段 | 描述 |
---|---|
pre-clean | 执行一些需要在clean之前完成的工作 |
clean | 移除所有上一次构建生成的文件 |
post-clean | 执行一些需要在clean之后立刻完成的工作 |
用户可以通过mvn pre-clean来调用clean生命周期中的pre-clean阶段需要执行的操作。
调用mvn post-clean会执行上面3个阶段所有的操作,上文中有说过,每个生命周期中的后面的阶段会依赖于前面的阶段,当执行某个阶段的时候,会先执行其前面的阶段。
default生命周期
这个是maven主要的生命周期,主要被用于构建应用,包含了23个阶段。
生命周期阶段 | 描述 |
---|---|
validate | 校验:校验项目是否正确并且所有必要的信息可以完成项目的构建过程。 |
initialize | 初始化:初始化构建状态,比如设置属性值。 |
generate-sources | 生成源代码:生成包含在编译阶段中的任何源代码。 |
process-sources | 处理源代码:处理源代码,比如说,过滤任意值。 |
generate-resources | 生成资源文件:生成将会包含在项目包中的资源文件。 |
process-resources | 编译:复制和处理资源到目标目录,为打包阶段最好准备。 |
compile | 处理类文件:编译项目的源代码。 |
process-classes | 处理类文件:处理编译生成的文件,比如说对Java class文件做字节码改善优化。 |
generate-test-sources | 生成测试源代码:生成包含在编译阶段中的任何测试源代码。 |
process-test-sources | 处理测试源代码:处理测试源代码,比如说,过滤任意值。 |
generate-test-resources | 生成测试源文件:为测试创建资源文件。 |
process-test-resources | 处理测试源文件:复制和处理测试资源到目标目录。 |
test-compile | 编译测试源码:编译测试源代码到测试目标目录. |
process-test-classes | 处理测试类文件:处理测试源码编译生成的文件。 |
test | 测试:使用合适的单元测试框架运行测试(Juint是其中之一)。 |
prepare-package | 准备打包:在实际打包之前,执行任何的必要的操作为打包做准备。 |
package | 打包:将编译后的代码打包成可分发格式的文件,比如JAR、WAR或者EAR文件。 |
pre-integration-test | 集成测试前:在执行集成测试前进行必要的动作。比如说,搭建需要的环境。 |
integration-test | 集成测试:处理和部署项目到可以运行集成测试环境中。 |
post-integration-test | 集成测试后:在执行集成测试完成后进行必要的动作。比如说,清理集成测试环境。 |
verify | 验证:运行任意的检查来验证项目包有效且达到质量标准。 |
install | 安装:安装项目包到本地仓库,这样项目包可以用作其他本地项目的依赖。 |
deploy | 部署:将最终的项目包复制到远程仓库中与其他开发者和项目共享。 |
site生命周期
site生命周期的目的是建立和发布项目站点,Maven能够基于pom.xml所包含的信息,自动生成一个友好的站点,方便团队交流和发布项目信息。主要包含以下4个阶段:
阶段 | 描述 |
---|---|
pre-site | 执行一些需要在生成站点文档之前完成的工作 |
site | 生成项目的站点文档 |
post-site | 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备 |
site-deploy | 将生成的站点文档部署到特定的服务器上 |
mvn命令和生命周期
从命令行执行maven任务的最主要方式就是调用maven生命周期的阶段,需要注意的是,每套生命周期是相互独立的,但是每套生命周期中阶段是有前后依赖关系的,执行某个的时候,会按序先执行其前面所有的。
mvn执行阶段的命令格式是:
mvn 阶段1 [阶段2] [阶段n]
多个阶段的名称之间用空格隔开。
下面我们举一些常见的例子来说明一下:
mvn clean
该命令是调用clean生命周期的clean阶段,实际执行的阶段为clean生命周期中的pre-clean和clean阶段。
mvn test
该命令调用default生命周期的test阶段,实际上会从default生命周期的第一个阶段(validate)开始执行一直到test阶段结束。这里面包含了代码的编译,运行测试用例。
mvn clean install
这个命令中执行了两个阶段:clean和install,从上面3个生命周期的阶段列表中找一下,可以看出clean位于clean生命周期的表格中,install位于default生命周期的表格中,所以这个命令会先从clean生命周期中的pre-clean阶段开始执行一直到clean生命周期的clean阶段;然后会继续从default生命周期的validate阶段开始执行一直到default生命周期的install阶段。
这里面包含了清理上次构建的结果,编译代码,测试,打包,将打好的包安装到本地仓库。
mvn clean deploy
这个命令也比较常用,会先按顺序执行clean生命周期的[pre-clean,clean]这个闭区间内所有的阶段,然后按序执行default生命周期的[validate,deploy]这个闭区间内的所有阶段(也就是default生命周期中的所有阶段)。这个命令内部包含了清理上次构建的结果、编译代码、运行单元测试、打包、将打好的包安装到本地仓库、将打好的包发布到私服仓库。
上面说了这么多理论,我们来看一下效果。
案例
创建一个maven项目
打开idea,点击File->New->Project,选择Maven,如下:
点击Next,输入项目坐标信息,如下:
点击Next,输入Project name 为maven-chat06,如下:
点击Finish,创建成功,如下:
配置一下idea的maven环境,点击File->Settings,如下图:
点击上面的OK完成配置。
还原~/.m2/settings.xml的配置到初始状态,操作如下:
将M2_HOME/conf/settings.xml复制到~/.m2/settings.xml目录,如果存在先备份一个,然后进行覆盖。
maven项目是约定大于配置的,项目结构是按照maven的约定生成好的,关于maven约定项目结构,我们再来回顾一下。
Maven 提倡使用一个共同的标准目录结构,Maven 使用约定优于配置的原则,大家尽可能的遵守这样的目录结构,如下所示:
结合刚才项目的结构和这个表格领会一下,下面我们来感受一下执行生命周期中的阶段产生的效果。
修改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.javacode2018</groupId>
<artifactId>maven-chat06</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 配置maven编译的时候采用的编译器版本 -->
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
<!-- 指定源代码是什么版本的,如果源码和这个版本不符将报错,maven中执行编译的时候会用到这个配置,默认是1.5,这个相当于javac命令后面的-source参数 -->
<maven.compiler.source>1.8</maven.compiler.source>
<!-- 该命令用于指定生成的class文件将保证和哪个版本的虚拟机进行兼容,maven中执行编译的时候会用到这个配置,默认是1.5,这个相当于javac命令后面的-target参数 -->
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
上面properties这个元素中的配置,可能大家看不懂,先略过,后面会详解。
创建一个Demo类,源码是放在src/main/java目录中,如下:
package com.javacode2018.maven;
import java.util.ArrayList;
import java.util.List;
public class Demo1 {
public static void main(String[] args) {
System.out.println("欢迎你");
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
list.add(i);
}
list.forEach(System.out::print);
}
}
mvn clean命令效果
在当前项目pom.xml所在目录中执行下面命令:
mvn clean
效果如下:
D:\code\IdeaProjects\maven-chat06>mvn clean
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< com.javacode2018:maven-chat06 >--------------------
[INFO] Building maven-chat06 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-chat06 ---
[INFO] Deleting D:\code\IdeaProjects\maven-chat06\target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.477 s
[INFO] Finished at: 2019-11-15T18:46:13+08:00
[INFO] ------------------------------------------------------------------------
上面有提到编译、打包的内容都放在target目录,看上面输出中有个Deleting target目录,说明mvn clean是对这个目录进行清理,这个目录中目前是空的。
mvn compile命令效果
先看一下项目的目录中是没有target目录的,如下图:
cmd中执行:
mvn compile
输出:
D:\code\IdeaProjects\maven-chat06>mvn compile
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< com.javacode2018:maven-chat06 >--------------------
[INFO] Building maven-chat06 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\code\IdeaProjects\maven-chat06\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.897 s
[INFO] Finished at: 2019-11-15T18:53:12+08:00
[INFO] ------------------------------------------------------------------------
可以看到上面有Compiling 1 source …,这个是编译Demo.java,然后输出到了target中的classes目录,再来看一下项目的结构,如下图:
上图中匡红的是新生成的。
mvn clean package效果
D:\code\IdeaProjects\maven-chat06>mvn clean package
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< com.javacode2018:maven-chat06 >--------------------
[INFO] Building maven-chat06 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-chat06 ---
[INFO] Deleting D:\code\IdeaProjects\maven-chat06\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\code\IdeaProjects\maven-chat06\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-chat06 ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-chat06 ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-chat06 ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ maven-chat06 ---
[INFO] Building jar: D:\code\IdeaProjects\maven-chat06\target\maven-chat06-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.177 s
[INFO] Finished at: 2019-11-15T18:56:59+08:00
[INFO] ------------------------------------------------------------------------
从输出中看一下,有个Building jar …,生成了一个jar包,这个项目的pom.xml中的packaging元素没有指定值,那就取默认值jar,表示这个构件是一个jar包,mvn clean package先清理编译的代码,然后执行了default生命周期的compile阶段,将项目打成了jar放在了target目录,如下图:
大家看到上面还有很多其他的输出,这个大家可以先忽略,本文看完了,都会明白的。
mvn clean install效果
D:\code\IdeaProjects\maven-chat06>mvn clean install
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< com.javacode2018:maven-chat06 >--------------------
[INFO] Building maven-chat06 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-chat06 ---
[INFO] Deleting D:\code\IdeaProjects\maven-chat06\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\code\IdeaProjects\maven-chat06\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-chat06 ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-chat06 ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-chat06 ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ maven-chat06 ---
[INFO] Building jar: D:\code\IdeaProjects\maven-chat06\target\maven-chat06-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ maven-chat06 ---
[INFO] Installing D:\code\IdeaProjects\maven-chat06\target\maven-chat06-1.0-SNAPSHOT.jar to C:\Users\Think\.m2\repository\com\javacode2018\maven-chat06\1.0-SNAPSHOT\maven-chat06-1.0-SNAPSHOT.jar
[INFO] Installing D:\code\IdeaProjects\maven-chat06\pom.xml to C:\Users\Think\.m2\repository\com\javacode2018\maven-chat06\1.0-SNAPSHOT\maven-chat06-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.977 s
[INFO] Finished at: 2019-11-15T19:05:21+08:00
[INFO] ------------------------------------------------------------------------
和mvn clean package的输出对比一下,多了几行输出,主要是多了2个Installing…,将项目打成jar包以及项目的pom文件放到本地仓库去了,也就是将构件打包安装到本地仓库了。
上面几个mvn命令的案例,都是通过mvn命令去执行了mvn中定义的生命周期中的阶段,然后完成了很多看似内部很复杂的操作。比如打包,内部包含很多复杂的操作,maven都帮我们屏蔽了,通过一个简单的mvn package就完成了。
转载:https://blog.csdn.net/m0_47157676/article/details/108367741