文章目录
1. maven概述
Maven 翻译为"专家"、“内行”,是 Apache 下的一个纯 Java 开发的开源项目。基于项目对象模型(缩写:POM:Project Object Model)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。
Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。也可被用于构建和管理各种项目,例如 C#,Ruby,Scala 和其他语言编写的项目。maven不仅是构建工具,还是依赖管理工具和项目信息管理工具,它提供了中央仓库,能帮我们自动下载构件。
构建(build)
除了编写源代码,编译、运行单元测试、生成文档、打包、部署等步骤都是构建。
约定配置
Maven 提倡使用一个共同的标准目录结构,Maven 使用约定优于配置的原则,大家尽可能的遵守这样的目录结构。如下所示:
${basedir} 存放pom.xml和所有的子目录
${basedir}/src/main/java 项目的java源代码
${basedir}/src/main/resources 项目的资源,比如说property文件,springmvc.xml
${basedir}/src/test/java 项目的测试类,比如说Junit代码
${basedir}/src/test/resources 测试用的资源
${basedir}/src/main/webapp/WEB-INF web应用文件目录,web项目的信息,比如存放web.xml、本地图片、jsp视图页面
${basedir}/target 打包输出目录
${basedir}/target/classes 编译输出目录
${basedir}/target/test-classes 测试编译输出目录
Test.java Maven只会自动运行符合该命名规则的测试类
~/.m2/repository Maven默认的本地仓库目录位置
2. Maven 安装
Maven 是一个基于 Java 的工具,所以要先安装 JDK。以windows系统为例,先检测jdk版本java -version,Maven 3.3 要求 JDK 1.7 或以上。
Maven 下载地址
windows系统使用bin.zip包下载安装,假设解压目录为:E:\Maven\apache-maven-3.3.9。
设置 Maven 环境变量:右键 “计算机”,选择 “属性”,之后点击 “高级系统设置”,点击"环境变量",来设置系统变量,有以下系统变量需要配置:新建系统变量 MAVEN_HOME,变量值:E:\Maven\apache-maven-3.3.9
编辑系统变量 Path,添加变量值: ;%MAVEN_HOME%\bin
保存退出即可。然后cmd进入操作命令窗口,mvn -v查看maven版本,如果能正常显示说明配置成功。
conf目录:该目录有一个非常重要的配置文件settings.xml。直接修改该文件即可在全局修改maven的行为。一般情况下,推荐将该文件复制到~/.m2/目录下,在用户范围内定制maven行为。如果一台机器上所有用户共用所有的maven配置,则直接配置全局范围。如果maven访问不了外网,还可以使用设置http代理来访问外网。
3.Maven三大生命周期
Maven拥有三套相互独立的生命周期,分别是clean、default和site.
3.1 clean Lifecycle: 在进行真正的构建之前进行一些清理工作。 mvn clean
clean的目的是清理项目。
每套生命周期都由一组阶段(Phase)组成,我们平时在命令行输入的命令总会对应于一个特定的阶段。
比如,运行mvn clean ,这个的clean是Clean生命周期的一个阶段。有Clean生命周期,也有clean阶段。
clean包含3个阶段:
1)pre-clean 执行一些清理前需要完成的工作
2)clean 清理上一次构建过程中生成的文件,比如编译后的class文件等
3)post-clean 执行一些清理后需要完成的工作
3.2 default Lifecycle: 构建的核心部分,编译,测试,打包,部署等等。
有23个阶段,下面只列出8个主要的阶段。
1)generate-resources: 生成包含在编译阶段中的任何源代码。
2) process-resource: 处理源代码,比如说,过滤任意值。
3) compile: 编译项目的源代码。一般来说:编译src/main/java目录下的java文件至项目输出的主classpath目录中
4) test-compile:编译项目的测试代码,是编译src/test/java目录下的java文件至项目输出的测试classpath目录中
5) test: 使用单元测试框架运行测试,测试代码不会被打包或部署.
6) package:将编译后的代码打包成可分发格式的文件,比如JAR、WAR或者EAR文件。
7) install:将包安装到Maven本地仓库,供本地其他Maven项目使用
8) deploy:将最终的包复制到远程仓库,供其他开发人员和Maven项目使用
运行任何一个阶段的时候,它前面的所有阶段都会被运行,这也就是为什么我们运行mvn install 的时候,代码会被编译,测试,打包。此外,Maven的插件机制是完全依赖Maven的生命周期的,因此理解生命周期至关重要。
3.3 site Lifecycle: 生成项目报告,站点,发布站点。
目的:建立和发布项目站点
pre-site 执行一些在生成项目站点之前需要完成的工作.
site 生成项目站点文档
post-site 执行一些在生成项目站点之后需要完成的工作.
site-deploy 将生成的项目站点发布到服务器
4. Maven 构建配置文件
构建配置文件是一系列的配置项的值,可以用来设置或者覆盖 Maven 构建默认值。
使用构建配置文件,你可以为不同的环境,比如说生产环境(Production)和开发(Development)环境,定制构建方式。
配置文件在 pom.xml 文件中使用 activeProfiles 或者 profiles 元素指定,并且可以通过各种方式触发。配置文件在构建时修改 POM,并且用来给参数设定不同的目标环境(比如说,开发(Development)、测试(Testing)和生产环境(Production)中数据库服务器的地址)。
构建配置文件大体上有三种类型:
项目级(Per Project) 定义在项目的POM文件pom.xml中
用户级 (Per User) 定义在Maven的设置xml文件中 (.m2/settings.xml)(仓库位置:没用过)
全局(Global) 定义在 Maven 全局的设置 xml 文件中 (/conf/settings.xml)(安装位置:不常用)
配置文件激活:(采用Pom.xml配置)
假设在src/main/resources文件夹下有三个用于测试文件:
env.properties 如果未指定配置文件时默认使用的配置。
env.test.properties 当测试配置文件使用时的测试配置。
env.prod.properties 当生产配置文件使用时的生产配置。
profile 可以让我们定义一系列的配置信息,然后指定其激活条件。这样我们就可以定义多个 profile,然后每个 profile 对应不同的激活条件和配置信息,从而达到不同环境使用不同配置信息的效果。
以下实例,我们将 maven-antrun-plugin:run 目标添加到测试阶段中。这样我们可以在不同的 profile 中输出文本信息。我们将使用 pom.xml 来定义不同的 profile,并在命令控制台中使用 maven 命令激活 profile。
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jsoft.test</groupId>
<artifactId>testproject</artifactId>
<packaging>jar</packaging>
<version>0.1-SNAPSHOT</version>
<name>testproject</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>test</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>Using env.test.properties</echo>
<copy file="src/main/resources/env.test.properties" tofile="${project.build.outputDirectory}/env.properties" overwrite="true"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>normal</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>Using env.properties</echo>
<copy file="src/main/resources/env.properties" tofile="${project.build.outputDirectory}/env.properties" overwrite="true"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>prod</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>Using env.prod.properties</echo>
<copy file="src/main/resources/env.prod.properties" tofile="${project.build.outputDirectory}/env.properties" overwrite="true"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
注意:构建配置文件采用的是 节点。
说明:上面新建了三个 ,其中 区分了不同的 执行不同的 AntRun 任务;而 AntRun 的任务可以这么理解,AntRun 监听 test 的 Maven 生命周期阶段,当 Maven 执行 test 时,就触发了 AntRun 的任务,任务里面为输出文本并复制文件到指定的位置;而至于要执行哪个 AntRun 任务,此时构建配置文件起到了传输指定的作用,比如,通过命令行参数输入指定的 。
执行命令:
mvn test -Ptest
提示:第一个 test 为 Maven 生命周期阶段,第 2 个 test 为构建配置文件指定的 参数,这个参数通过 -P 来传输,当然,它可以是 prod 或者 normal 这些由你定义的。
5. Maven 仓库
在 Maven 的术语中,仓库是一个位置(place)。Maven 仓库是项目中依赖的第三方库,这个库所在的位置叫做仓库。
在 Maven 中,任何一个依赖、插件或者项目构建的输出,都可以称之为构件。
Maven 仓库能帮助我们管理构件(主要是JAR),它就是放置所有JAR文件(WAR,ZIP,POM等等)的地方。
Maven 仓库有三种类型:
本地(local)
中央(central)
远程(remote)
本地仓库
Maven 的本地仓库,在安装 Maven 后并不会创建,它是在第一次执行 maven 命令的时候才被创建。
运行 Maven 的时候,Maven 所需要的任何构件都是直接从本地仓库获取的。如果本地仓库没有,它会首先尝试从远程仓库下载构件至本地仓库,然后再使用本地仓库的构件。
默认情况下,不管Linux还是 Windows,每个用户在自己的用户目录下都有一个路径名为 .m2/repository/ 的仓库目录。
Maven 本地仓库默认被创建在.m2/repository/目录下。要修改默认位置,在安装目录下的conf 目录中的 Maven 的 settings.xml 文件中定义另一个路径。
中央仓库 搜索起来比较方便,推荐使用。
可以用 maven仓库的网址 进行搜索, 也可以在阿里巴巴的镜像上进行索引.
Maven 中央仓库是由 Maven 社区提供的仓库,其中包含了大量常用的库。
远程仓库
如果 Maven 在中央仓库中也找不到依赖的文件,它会停止构建过程并输出错误信息到控制台。为避免这种情况,Maven 提供了远程仓库的概念,它是开发人员自己定制仓库,包含了所需要的代码库或者其他工程中用到的 jar 文件。
Maven 将从远程仓库中下载该 pom.xml 中声明的所依赖的(在中央仓库中获取不到的)文件。
Maven 依赖搜索顺序:
在本地仓库中搜索,如果找不到,去远程仓库找(若配置的有)如果找到则下载到本地仓库以备将来引用,如果还找不到,去中央仓库中搜索,还找不到 Maven 将停止处理并抛出错误(无法找到依赖的文件)。
6. Maven 创建 Java 项目
Maven 使用原型 archetype 插件创建项目。要创建一个简单的 Java 应用,我们将使用 maven-archetype-quickstart 插件。
archetype 也就是原型,是一个 Maven 插件,准确说是一个项目模板,它的任务是根据模板创建一个项目结构。
在 C:\MVN 文件夹下创建一个基于 maven 的 java 应用项目。
命令格式如下:
mvn archetype:generate “-DgroupId=com.companyname.bank” “-DartifactId=consumerBanking” “-DarchetypeArtifactId=maven-archetype-quickstart” “-DinteractiveMode=false”
参数说明:
-DgroupId: 组织名,公司网址的反写 + 项目名称
-DartifactId: 项目名-模块名
-DarchetypeArtifactId: 指定 ArchetypeId,maven-archetype-quickstart,创建一个简单的 Java 应用
-DinteractiveMode: 是否使用交互模式
Maven 自动化构建
自动化构建定义了这样一种场景: 在一个项目成功构建完成后,其相关的依赖工程即开始构建,这样可以保证其依赖项目的稳定。
比如一个团队正在开发一个项目 A, 并且有其他两个项目 B 和 C依赖于这个项目。
B 、C项目使用的是 A 项目的 1.0 快照:
在A项目的plugin标签下添加如下配置
<configuration>
<debug>true</debug>
<pomIncludes>
<pomInclude>C/pom.xml</pomInclude>
<pomInclude>D/pom.xml</pomInclude>
</pomIncludes>
</configuration>
7. Maven 依赖管理
POM文件结构:
文件第一行是XML文件头,定义了xml的版本和编码方式。第二行是标签,该标签是根标签,它还定义了一些命名空间和xsd元素,方便第三方编辑器编辑xml文件。
modelVersion :模型版本需要设置为 4.0。对于maven2和maven3都是4.0。
name:模块名称,以后生命周期显示都使用该名称。
接下来就是groupId,artifactId,version这三个最核心的标签,具体介绍见下方。
Maven的仓库中拥有着无数的构件,每一个构件都是一个jar或者war等文件。Maven定义了一组规则:仓库中任何一个构件都可以使用Maven坐标来唯一标识。Maven坐标的主要元素包括groupId,artifactId,version,packaging(可选)和classifier(可选),通过这些元素,我们可以明确标识任何一个构件。无论是从本地仓库引用jar包,还是从远程仓库下载jar包, 使用坐标来表示 jar包。
groupId 表示公司/组织名, 常常用 域名反写,如 阿里巴巴 是 com.alibaba
artifactId 表示项目名, 哪个项目,如 fastjson
version 表示版本号, 如 1.2.72,包括稳定(release)版本和测试(snapshot)版本
packaging:表示Maven项目的打包方式,默认为jar,还有war和pom方式。聚合工程必须为pom。
classifer:用来定义构件输出的一些附属构件,例如通过配置插件。
那么 com.alibaba.fastjson-1.2.72.jar 就可以表示出 阿里巴巴公司的fastjson项目 1.2.72版本的jar包了。
那么想要引入fastjson的依赖,坐标就可以写成:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.72</version>
</dependency>
maven依赖传递
依赖的传递性也分为三种。
直接依赖:在当前项目中通过依赖配置建立的依赖关系
间接依赖:被资源的资源如果依赖其他资源,当前项目间接依赖其他资源
特殊优先:当同级配置了相同资源的不同版本,后配置的覆盖先配置的
直接依赖就是我们直接写的依赖,间接依赖就是我们写的依赖又依赖的其他的依赖。
可选依赖optional
依赖是有传递性的,模块A里面依赖了一些东西,现在B模块想要依赖A模块,但是A模块不想让B知道我依赖了哪些东西,A想把这些东西隐藏起来。配置在A。使标签。true就是隐藏,默认不隐藏。==可选依赖不推荐使用,不符合单一职责原理。==一般出现可选依赖是某个项目实现多个特性,这种建议把项目拆分。
排除依赖exclusion
排除依赖跟可选依赖优点相似,可选依赖是自己隐藏,不对外公布。排除依赖是,B依赖了A,而A的依赖中有的依赖B不想要,这个时候我就可以使用排除依赖进行排除,配置在B。使用。true就是排除,默认不排除。
依赖范围scope
Maven有如下6种依赖范围:
compile: 编译依赖范围(Default,大多数情况下我们都是在使用compile编译范围)
test: 测试依赖范围 (编译主代码和运行时无效,编译测试代码和运行测试代码有效)
provided: 已提供依赖范围(就是说在运行的时候容器已经给我们提供该依赖了)
runtime: 运行时依赖范围(对于测试和运行代码有效,对编译代码无效)
system: 系统依赖范围(生成的构建一般与本机系统绑定,不具备移植性不建议使用)
import: 导入依赖范围(将其它地方官依赖配置导入)
依赖范围 | 编译时有效 | 测试时有效 | 运行时有效 |
---|---|---|---|
compile | Y | Y | Y |
test | N | Y | N |
provided | Y | Y | N |
runtime | N | Y | Y |
system | Y | Y | N |
依赖范围会对传递依赖产生影响。
|–|–|–|–|–|
| |compile |test |provided |runtime|
| compile |compile |-- |-- |runtime|
| test |test |-- |-- |test |
| provided |provided |-- |provided |provided |
| runtime|runtime|-- |-- |runtime|
归类依赖properties
归类依赖看着高大上,其实说白了就是为了统一管理依赖,如果某些依赖的version都是一致的或者是存在某些特殊的关系,我们可以在pom中使用配置一些变量,在下边的时候使用$变量名来引用。
dependencyManagement
dependencyManagement既能让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活性。在dependencyManagement元素下的依赖声明不会引入实际依赖,但能够约束depencies下的依赖使用。在父模块中dependencyManagement下定义的依赖,既不会给父模块引入该依赖,也不会给子模块引入该依赖,不过这块依赖会被子模块继承。父模块在使用这种方式定义以后,子模块只需要引入groupId和artifactId即可。
import
作用范围import只有在dependencyManagement元素下才有效果。如果想获得和另一个模块一样的dependencyManagement配置,除了复制和继承以外,还可以使用import。引入时,在代码中依赖的type为pom,import范围因为其特殊性,一般都是指向打包类型为pom的模块。
8. Maven 快照(SNAPSHOT)
一个大型的软件应用通常包含多个模块,并且通常的场景是多个团队开发同一应用的不同模块。假设B模块依赖A模块
现在可能出现的情况是开发 A 的团队正在进行快节奏的 bug 修复或者项目改进,并且他们几乎每隔一天就要发布库到远程仓库。 现在如果A 团队每隔一天上传一个新版本,那么将会出现下面的问题:
A团队每次发布更新的代码时都要告知 B团队。
B团队需要经常地更新他们 pom.xml 文件到最新版本。
为了解决这种情况,快照的概念派上了用场。
快照是一种特殊的版本,指定了某个当前的开发进度的副本。不同于常规的版本,Maven 每次构建都会在远程仓库中检查新的快照。 现在A团队会每次发布更新代码的快照到仓库中。
项目快照 vs 版本
对于版本,如果 Maven 以前下载过指定的版本文件,比如说 data-service:1.0,Maven 将不会再从仓库下载新的可用的 1.0 文件。若要下载更新的代码,data-service 的版本需要升到1.1,或者删除本地仓库中的1.0版本然后重新下载该依赖包。
快照的情况下,每次B团队构建他们的项目时,Maven 将自动获取最新的快照(data-service:1.0-SNAPSHOT)。
Maven版本号定义约定:
主版本.次版本.增量版本-里程碑版本
主版本:项目重大架构变更
次版本:大范围功能增加和变化及bug修复
增量版本:重大的bug修复
里程碑版本:版本的一个里程碑,不是很稳定
9.重复依赖选择原则
重复依赖选择原则:
最短路径原则: 两级以上的不同级依赖, 选择路径最短
声明优先原则 : 两级以上的同级依赖,先声明的覆盖后声明的
同级依赖后加载覆盖先加载原则(两级依赖)
最短路径原则
最短路径原则的前提是:两级以上的不同级依赖, 选择路径最短
A–>B–>C–>D(1.2.3)
A–>F–>D(1.0.2)
最终选择依赖的D版本就是1.0.2,因为是两级以上,路径AFD最短。
使用idea的maven工具就可以查看依赖冲突的具体情况。omitted for conflict with version
使用 mvn dependency:tree 命令可以查看 项目的依赖树
声明优先原则
A–>B–>D(1.2.3)
A–>C–>D(1.0.2)
因为上述二者属于两级以上的同级依赖,所以先定义者先使用。即使用D的版本是1.2.3
两级依赖后加载优先:
A–>D(1.2.3)
A–>D(1.0.2)
因为是两级依赖,所以后加载的会覆盖先加载的。
idea插件安装目录,直接把jar包或文件夹复制到该目录再重启idea即可,目录在C盘并不在安装目录。
C:\Users\用户名.IntelliJIdea2018.3\config\plugins
常用插件:MybatisX(mapper接口和mapper.xml文件互相跳转)、maven helper(分析maven依赖)
maven helper使用方法
maven helper的入口就在pom文件,打开pom文件后,点击Dependency Analyzer按钮,然后选择conflicts按钮,就可以看到是哪些jar包冲突了。左边的列表展示的是冲突的jar包,右边的列表展示的是选中某一个具体的jar包后,该pom文件中所有依赖该jar包的地方。其中红色代表冲突的jar包版本。选中某一个冲突的jar包版本,右键点击即可跳转到具体的依赖引入的地方。同时,还可以搜索jar包,搜索某个jar包是否被引入以及是怎么引入的。
10. maven聚合与继承
聚合和继承打包的方式都是pom,且都没有实质的内容。
Maven的聚合:可以把项目的多个模块聚合在一起,使用一条命令进行构建,即一条命令实现构建多个项目;
Maven的继承:可以将各个模块相同的依赖和插件配置提取出来,在简化POM的同时还可以促进各个模块配置的一致性。
maven聚合通过和标签进行聚合。聚合模块仅仅是帮助聚合其他模块构建的工具,所以本身并无实际内容。聚合模块打包方式必须为pom,否则无法构建。
继承
将各个子模块相同的依赖和插件配置提取出来到父模块,从而简化配置文件。父模块的打包方式必须为pom,否则无法构建项目。
子模块中通过标签来表明其继承于哪一个父模块,就可以继承父模块的配置。聚合模块和父模块经常合二为一,但是聚合和继承是两个不同的概念。
聚合和继承的关系
聚合模块知道它聚合了哪些模块,但是被聚合的模块不知道聚合模块的存在。
父模块不知道子模块的存在,但是子模块都必须知道自己的父模块是谁。
11. 反应堆
反应堆:所有模块的构建结构。模块间的依赖关系会将反应堆构成一个有向非循环图,各个模块是该图的节点,依赖关系构成有向边。当出现循环时,maven构建就会出错。
裁剪反应堆
裁剪反应堆:构建完整反应堆中的某些个模块。
Maven提供了很多的命令行选项支持裁剪反应堆:
-am:同时构建所列模块的依赖模块
-amd:同时构建依赖于所列模块的模块
-pl:构建指定的模块,模块间用逗号分隔
-rf:完整的反应堆构建顺序基础上指定从哪个模块开始构建
在 -pl -am 或者 -pl -amd 的基础上,还能应用 -rf 参数,以对裁剪后的反应堆再次裁剪,例如执行命令:
mvn clean install -pl A -amd -rf B
12. Maven 插件
Maven 有以下三个标准的生命周期:clean:项目清理的处理;default(或 build):项目部署的处理;site:项目站点文档创建的处理
每个生命周期中都包含着一系列的阶段(phase)。这些 phase 就相当于 Maven 提供的统一的接口,然后这些 phase 的实现由 Maven 的插件来完成。
我们在输入 mvn 命令的时候 比如 mvn clean,clean 对应的就是 Clean 生命周期中的 clean 阶段。但是 clean 的具体操作是由 maven-clean-plugin 来实现的。
所以说 Maven 生命周期的每一个阶段的具体实现都是由 Maven 插件实现的。
Maven 实际上是一个依赖插件执行的框架,每个任务实际上是由插件完成。
插件是在 pom.xml 中使用 plugins 元素定义的。每个插件可以有多个目标。
你可以定义阶段,插件会使用它的 phase 元素开始处理。
你可以通过绑定到插件的目标的方式来配置要执行的任务。
基本上所有的maven插件都来自于Apache和Codehaus,Apache的属于官方插件,文档比较齐全,Codehaus有的文档不全。
管理插件pluginManagement
在pluginManagement元素下配置的插件不会发生实际调用,只有当pom中配置了真正的插件且与pluginManagement中声明的一致,才会发生真正的调用。子模块只需要引入groupId和artifactId即可,这与dependencyManagement类似。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
maven核心插件
12.1 maven-compiler-plugin
maven-compiler-plugin:对应生命周期compile,编译主代码到主输出目录。
默认编译Java1.3,所以要配置标签指定编译的版本。maven-compiler-plugin插件打包的jar是不能直接运行的,因为带有main方法的类信息不会被添加到manifest中(META-INF/MANIFEST.MF)
12.2 maven-jar-plugin
maven-jar-plugin:对应生命周期package,创建项目jar包。
可以通过mvn help:describe命令来查看插件、命令等操作的详细说明,比如我们在命令行执行mvn help:describe -Dplugin=org.apache.maven.plugins:maven-jar-plugin,便可以看到maven-jar-plugin插件的详细介绍
jar项目默认的打包工具,默认情况下只会将项目源码编译生成的class文件和资源文件打包进来,不会打包进项目依赖的jar包。
打成jar时,设定manifest的参数,比如指定运行的Main class,还有依赖的jar包,加入classpath中
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>/data/lib</classpathPrefix>
<mainClass>com.atguigu.Application</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
12.3 maven-surefire-plugin
Maven 2/3中用于执行测试的插件maven-surefire-plugin。
其实大部分时间内,只要你的测试类遵循通用的命令约定(以Test结尾、或者以Test开头),就几乎不用知晓该插件的存在。当想要跳过测试、排除某些测试类、或者使用一些TestNG特性的时候就需要了解。
例如 mvn test -Dtest=FirstTest 这样一条命令的效果是仅运行FirstTest 测试类,这是通过控制maven-surefire-plugin的test参数实现的。
12.4 exec-maven-plugin
exec-maven-plugin:它能让你运行任何本地的系统程序
exec-maven-plugin 插件有 2 个目录 (goal),一个是 java 一个是 exec。这里简单解释一下 maven 的 goal,可以把 maven 的 goal 看做是一个特定的功能,一个 maven 插件可能有很多功能,一个功能就是一个 goal,maven 还有生命周期的概念,maven 有 3 套生命周期,分别是 clean,default,site。每一个生命周期有包含一下阶段 (phase),可以把每一个阶段看做一个流程。参加后面的 maven 生命周期。
上面的 2 个命令都包含了 2 个生命周期,clean 和 default 生命周期。clean 会执行 clean 生命周期的 pre-clean 和 clean 阶段,mvn clean package 命令会从 default 生命周期会从 validate 执行到 package 阶段,mvn clean test 命令会从 default 生命周期的 validate 阶段执行到 package 阶段。
插件就是把 goal 绑定到生命指定阶段的上执行的。就是 maven 在执行相应阶段的时候会检查有那些插件的 goal 绑定到这个阶段上的,然后执行这些 goal。
:在构建生命周期中执行一组目标的配置。每个目标可能有不同的配置。 execute 激活
:execution元素包含了插件执行需要的信息
: 执行目标的标识符,用于标识构建过程中的目标,或者匹配继承过程中需要合并的执行目标
:绑定了目标的构建生命周期阶段,如果省略,目标会被绑定到源数据里配置的默认阶段
:配置的执行目标
:配置是否被传播到子POM
:作为DOM对象的配置
phase元素代表的是绑定的生命周期的阶段
goals元素代表插件的目标,插件是前面artifactId中定义好的,goals相当于该插件中的一个功能,该功能将在phase绑定的生命周期阶段执行
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<!-- 绑定到编译的生命周期 -->
<phase>compile</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.atguigu.Application</mainClass>
</configuration>
</plugin>
这个配置会在编译时执行Application类的man方法。
12.5 maven-assembly-plugin
maven-assembly-plugin:构建自定义格式的分发包
工作中maven-assembly-plugin使用较多,因为项目中往往有很多shell脚本、.yml、.properties及.xml配置项等,采用assembly插件可以让输出的结构清晰且标准化。
12.5.1 参考build配置
参考配置:以下配置并不是全部需要,看情况选取所需要的插件
<build>
<finalName>${project.artifactId}-${service.version}</finalName>
<plugins>
<plugin>
<!-- compiler编译插件参数设置,指定jdk版本 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!--去掉jar的配置文件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.yml</exclude>
<exclude>**/*.xml</exclude>
<exclude>META-INF/**/*</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<!-- 这个是assembly 所在位置 -->
<descriptor>src/main/assembly/assembly.xml</descriptor>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- 绑定到maven package生命周期 -->
<phase>package</phase>
<goals>
<!-- 只执行一次 -->
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.atguigu.Application</mainClass>
</configuration>
</plugin>
<plugin>
<!-- 测试插件,skip为true代表跳过测试 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skip>true</skip>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</build>
12.5.2 assembly.xml配置
<assembly>
<formats>
<!--支持 zip,tar,tar.gz,tar.bz2,jar,dir,war 等 -->
<format>tar.gz</format>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>src/main/resources</directory>
<outputDirectory>conf</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
<fileSet>
<directory>${profile.dir}</directory>
<outputDirectory>conf</outputDirectory>
<!-- 表示的是包含下面格式的资源文件 -->
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
<fileMode>0644</fileMode>
</fileSet>
<fileSet>
<directory>src/main/assembly/bin</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
id与formats
formats是assembly插件支持的打包文件格式,有zip、tar、tar.gz、tar.bz2、jar、war。可以同时定义多个format。
id则是添加到打包文件名的标识符,用来做后缀。
fileSets/fileSet
用来设置一组文件在打包时的属性。
directory:源目录的路径。
includes/excludes:设定包含或排除哪些文件,支持通配符。
fileMode:指定该目录下的文件属性,采用Unix八进制描述法,默认值是0644。
outputDirectory:输出目录。
files/file
与fileSets大致相同,不过是指定单个文件,并且还可以通过destName属性来设置与源文件不同的名称。
dependencySets/dependencySet
用来设置工程依赖文件在打包时的属性。也与fileSets大致相同,不过还有两个特殊的配置:
unpack:布尔值,false表示将依赖以原来的JAR形式打包,true则表示将依赖解成*.class文件的目录结构打包。
scope:表示符合哪个作用范围的依赖会被打包进去。compile与provided都不用管,一般是写runtime。
按照以上配置打包好后,将.tar.gz文件上传到服务器,解压之后就会得到bin、conf、lib等规范化的目录结构,十分方便。
与UNIX权限类似,设置所包含文件的文件模式。这是一个八进制值。格式:(用户)(组)(其他),其中每个组件是读取=4、写入=2和执行=1的总和。例如,值0644转换为用户读写、组和其他读取。如0755, 0644.
ABCD
A- 0, 表示十进制
B-用户
C-组用户
D-其他用户
— -> 0 (no excute , no write ,no read)
–x -> 1 excute, (no write, no read)
-w- -> 2 write
-wx -> 3 write, excute
r-- -> 4 read
r-x -> 5 read, excute
rw- -> 6 read, write ,
rwx -> 7 read, write , excute
0755->即用户具有读/写/执行权限,组用户和其它用户具有读写权限;
0644->即用户具有读写权限,组用户和其它用户具有只读权限;
一般赋予目录0755权限,文件0644权限。
参考:
菜鸟教程: Maven 教程
《Maven实战》:许晓斌著