学习视频地址
《Maven实战》
mvn
mvn
- -v 查看maven版本
- compile 编译
- test 测试
- package 打包 默认jar
- clean 删除target
- install 安装jar包到本地仓库 在根目录运行mvn install 就会将当前的jar 安装到本地仓库
- 在编译的时候 如果程序用到了其他支持包就会在pom.xml查找是否引入该包的坐标 引入该坐标后,就会去本地仓库查找,如果有jar包mvn就会加入到项目的CLASSPATH,如果没有就会去MVN的远程中央仓库下载到本地仓库。
自动创建目录骨架
- archetype:generate按照提示进行选择
- archetype:generate -DgroupId=组织名,域名反转+项目名。-DartifactId=项目名-模块名-Dversion=版本号 -Dpackage=代码所存在的包名
- 经测试groupid 和artifactId 对本地编译 运行测试均没有影响。对打包后的文件有影响,命名为:“arttifactId-version.jar”(以生成jar文件为例,以下均以生成jar文件为例)groupid 和artifactId 还有version是在仓库中安装的文件的目录,目录依次是groupID/artifactId/version/artifactId-version.jar 在eclipse中,artifactId就是项目名,groupId就是默认包名
问题:package的作用
- 项目的包
- 坐标 也就是在仓库中的路径,具有唯一标示
- 构件
仓库
- 依赖和坐标的对应关系:参照上节中加粗部分
- 本地仓库
- 默认的本地仓库是
C:\Users\ZDQ\.m2\resposity\
其中ZDQ是笔者电脑的用户名。 - 更改默认仓库:
- 复制安装目录下的
/conf/settings.xml
到~/.m2/settings.xml
- 复制安装目录下的
- 默认的本地仓库是
<settings>
<localRespository>
新的仓库地址
</loacalRespository>
</settings>
- 远程仓库
- 中央仓库
- 私服
- 其他公共库
- 配置
- 可以声明多个远程仓库,任何仓库的id必须是唯一的,Maven自带的仓库id为central,如果其他的仓库声明也使用该id ,就会覆盖中央仓库的配置
<releases>
- 表示是否开启该仓库的发布版下载支持。
<snapshots>
- 表示是否开启仓库的快照版本下载支持。
- 以上两个标签还有两个子标签:
<updatePolicy>
- daily -默认值,表示每天检查一次。
- never -从不检查。
- always -每次构建都检查更新。
- interval:X -每隔X分钟检查一次更新(X为任意整数)。
<checksumPolicy>
- 配置Maven 检查校验和文件的策略,当构件被部署到Maven仓库中时,会同时部署对应的校验和文件,在下载构建的时候,Maven会验证校验和文件,如果校验和验证失败时,有以下几种情况
- warn 默认值 Maven会在构建时输出警告信息。
- fail 遇到校验和错误就让构建失败。
- ignore 使Maven完全忽略校验和错误。
- 配置Maven 检查校验和文件的策略,当构件被部署到Maven仓库中时,会同时部署对应的校验和文件,在下载构建的时候,Maven会验证校验和文件,如果校验和验证失败时,有以下几种情况
- 远程仓库的认证
- 在setting.xml中部署 其中的id 将认证信息与仓库配置联系在了一起。
- 部署至远程仓库
<distibutionManagement>
<reponsitory>
:表示发布版本构件的仓库<snapshotRepository>
表示快照版本的仓库
<project>
...
<repositories>o
<reposiory>
<id>jboss</id>
<name>JBoss Repository</name>
<url>http://</url>
<releases>
<enabled>true</enables>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<layout>default</layout>
</repository>
</repository>
...
</project>
<settings>
...
<servers>
<server>
<id></id>
<username></username>
<password></password>
</server>
</servers>
...
<settings>
* 镜像仓库 在confg/setting.xml 146行
* 更改仓库位置
* 53行setting中 然后复制到 新仓库中
maven生命周期
- Maven的声明周期是抽象的,其实际行为都由插件来完成。
- 每个生命周期包含一些阶段,这些阶段是有顺序的,并且后面的阶段依赖前面的阶段。
Maven有三套相互独立的生命周期
- clean 生命周期
- 清理项目
- pre-clean 执行一些清理前需要完成的工作
- clean 清理上一次构建生成的文件
- post-clean 执行一些清理后需要完成的工作
default 生命周期
- 构建项目
- validate
- initialize
- generate-source
- proces-sources 处理项目主资源文件,一般来说,是对src/mian/resource目录的内容进行变量替换工作后,复制到项目输出的主classpath目录中。
- generate-resources
- process-resource
- compile 编译项目的主源码,一般来说,是编译src/main/java目录下的java文件至项目输出的主classpath目录中。
- process-classes
- generate-test-sources
- process-test-sources 处理项目测试资源文件。一般来说,是对src/test/resources目录的内容进行变量替换等工作后,复制到项目输出的测试classpath目录中。
- generate-test-resource
- post-test-resource
- test-compile 编译项目的测试代码。一般来说,是编译src/test/java目录下的java文件至项目输出的测试classpath目录中。
- process-test-classes
- test 使用单源测试框架运行测试,测试代码不会打包或被部署
- prepare-package
- package 接受编译好的代码,打包成可发布的格式,如JAR
- pre-integration-test
- integration-test
- post-integration-test
- verify
- installn 将包安装到Maven本地仓库,供本地其他Maven项目使用。
- deploy 将最终的包复制到远程仓库,供其他开发人员和Maven项目使用。
site生命周期
- 建立项目站点
- pre-site 执行一些在生成项目站点之前需要完成的工作。
- site 生成项目站点文档
- post-site 执行一些在生成项目站点之后需要完成的工作。
- site-deploy将生成的项目站点发布到服务器上。
- clean 生命周期
- 插件
- 插件目标
- Maven的核心仅仅定义了抽象的声明周期,具体的任务是交由插件完成的,插件以独立的构件形式存在。
- 每个目标对应一个功能。通用写法:‘插件前缀:目标’
- 插件绑定
- 生命周期的阶段与插件的目标相互绑定。
- 内置绑定
- Maven在一些主要的生命周期阶段绑定插件目标。
- 自定义绑定
- 插件目标被绑定到不同的生命周期阶段时,其执行顺序会由生命周期阶段的先后顺序决定如果多个目标被绑定到同一个阶段,这些插件声明的先后顺序决定了目标的执行顺序。
- 在配置插件时,如果该插件时Maven的官方插件,即groupId为org.apache.maven.plugins。就可以省略groupId配置。(不推荐)
- Maven的核心仅仅定义了抽象的声明周期,具体的任务是交由插件完成的,插件以独立的构件形式存在。
- 插件目标
pom.xml
- pom.xml解析
<project>
根目录<modekVersion>
指定当前pom的版本<groupId>
一般是组织域名反转<artifact>
一般是项目名-模块名<version>
当前项目版本号 第一个0大版本号 0 表示分支版本号 0 表示小版本号 snapshot(表示该项目处在开发之中,是不稳定的版本) alfa beta release 等。<package>
打包方式 默认jar ,可以是war zip pom等。<name>
项目的描述名<url>
项目地址<description>
项目描述<developers>
<licenses>
<organization>
<dependencies>
依赖项
<dependency>
坐标
<groupId>
<artifact>
<version>
<type>
<scope>
依赖范围 例如 test junit 在测试依赖范围内有用<optional>
true false 设置依赖是否可选 默认false 子项目 继承<exclusions>
<exclusion>
排除以来传递列表
<dependencyMnagement>
<dependencies>
<d>
<build>
<plugins>
插件列表<plugin>
要指出坐标
<modules>
指定多个模块
依赖范围
- 依赖范围
<SCOP></SCOP>
- 三种classpath 编译、测试、运行
- 六种依赖范围
- compile (默认) 编译测试运行都有效
- provided 测试编译时有效
- runtime 测试运行时有效
- test 只在测试时有效
- system 测试编译时有效 与本机系统相关联,可移植性差
- import 导入范围只使用在dependencyManagement中,表示从其他的pom中导入depenfecy的配置
依赖
依赖传递
- B 依赖C A依赖B A就会依赖C
依赖排除
xml
<exclusions>
<exlusion>
<groupId>
<artifactId>
</artifactId>
</groupId>
</exlusion>
<exclusions>
依赖冲突
B 和C 分别依赖了不同版本的相同构件,对于依赖BC的A来说应该依赖哪一个构件呢?
- 短路优先 优先解析路径短的版本(依赖传递最少的,不是实际路径长度)
- 第一声明者优先,如果路径长度相同,则优先解析在
<dependencies>
中 先声明的,不会被覆盖。 - 这两个原则就确定依赖的唯一性
可选依赖
- 不会被传递
归类依赖
- 使用properties元素定义Maven属性
- ${}引用Maven属性。这和java的外部配置文件类似
优化依赖
- 查看当前项目已解析的依赖: mvn dependency:list
- 查看当前项目已解析的依赖树:mvn dependency:tree
- 分析当前的项目依赖:mvn dependency:analyze
- Used undeclared dependencies
- 意指项目中使用到的,但是没有显示的声明依赖,这种依赖是通过直接依赖传递进来的,当升级直接依赖的时候,相关的传递依赖的版本可能也会发生变化,如果其中的接口发生改变,项目就会出现错误,这种隐藏的、潜在的威胁一旦出现,就往往耗费大量的时间来查明,因此显示声明任何项目中直接用到的依赖。
- Unused declared dependencies
- 意指 项目中未使用的,但显示声明的依赖。对于这样一类依赖我们不应该简单地删除其声明而是应该仔细分析。dependency:analyz只会分析编译主代码和测试代码需要用到的依赖,分析不了一些执行测试和运行时需要的依赖
- Used undeclared dependencies
聚合和继承
- 聚合:即多模块。将多个项目的命令 一起运行 也就是命令作用于多个项目
- 使用
<modules>
<module>
项目的路径<module>
- 每个module的值都是一个当前POM的相对目录。
- 通常将聚合模块放在项目目录的最顶层。其他模块作为聚合模块的子目录存在。
- 将
<package>
设置为pom 否则无法构建。(不明白) - 运行
- 使用
- 继承
- 父模块只是为了帮助消除配置的重复。本身不包含除POM之外的项目文件,没有src/main/java之类的文件。
<parent>父类坐标</parent>
- Maven会首先根据relativePath检查父POM,如果找不到,再从本地仓库查找。其默认值是../pom.xml 即默认父POM在上一层目录下。
- 子模块会隐式地从父模块继承groupId和version。如果子模块和父模块不一样,可以在子模块中显式的声明。
- 可继承的POM元素
- groupId
- version
- description
- orgnization
- inceptionYears
- url
- developers
- contributors
- distributionManagement
- issuseManagement
- ciManagement
- scm
- mailingLists
- properties
- dependencyManagement
- repositories
- build
- reporting
- 依赖管理
<dependencyManagement>
元素既能让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活性。- 使用
<dependencyManagement>
声明的依赖即不会引入依赖,也不会给他的子模块引入依赖。但这段配置是可以继承的。 - 在子类中,依赖配置较原来就简单了。可以在子类中只配置groupId和artifactId ,省去了version。因为完整的依赖声明已经包含在父POM中。 这样可以统一项目范围中依赖的版本,帮助降低依赖冲突的几率。
- 如果子模块不声明依赖的使用,即使该依赖已经在父POM的dependencyManangement中声明了,也不会产生任何实际的效果。
- 如果想要在某个模块中使用和另一个模块中完全一样的dependencyManagement配置,除了赋值和继承外,还可以使用import范围依赖将这一配置导入。import 只有在dependencyManagement元素下才有效 p134
- 插件管理
- Maven 提供了dependencyManagement元素帮助管理依赖,类似地,Maven也提供了pluginManagement元素帮助管理插件。
- 超级POM
- 在这里定义了仓库,项目结构,插件版本等信息。所有的POM都隐式的继承了该POM
- 反应堆 Reactor
- 是指所有模块组成的一个构建结构。对于单模块的项目,反应堆就是该模块本身,对于多模块项目来说,反应堆就包含了各模块之间继承与依赖的关系从而能自动计算出合理的模块 构建顺序。
- 反应堆的构建顺序
- Maven按顺序读取POM,如果该POM没有依赖模块,就构建该模块,否则就先构建其依赖的模块。以此类推。
- 裁剪反应堆
- -am ,–also-make 同时构建所列模块的依赖模块。
- -amd,-also-make-dependents同时构建依赖于所列模块的模块。也就是 构建所列模块,和其子模块。
-pl,--project <arg>
构建指定的模块,模块间用逗号分隔-rf ,-resume-from <arg>
从指定的模块回复反应堆。回复???从当前模块顺序构建???
- 将
<packaging>
设置为pom 否则无法构建。(不明白)
注意:应该尽可能的不去修改任何Maven安装目录下的文件
* 安装目录下的文件是全局的,整台机器上的所有用户都会受到影响,应该在用户目录下修改,
* 不便于升级,每次升级新版本的Maven都要重新配置。