目录
Project Object Model:项目对象模型。将 Java 工程的相关信息封装为对象作为便于操作和管理的模型。Maven 工程的核心配置,可以说学习 Maven 就是学习 pom.xml 文件中的配置。
Maven 的坐标
使用如下三个向量在 Maven 的仓库中唯一的确定一个 Maven 工程。
[1]groupid:公司或组织的域名倒序+当前项目名称
[2]artifactId:当前项目的模块名称
[3]version:当前模块的版本
将 gav 三个向量连起来
g:groupid
a:artifactid
v:version
以连起来的字符串作为目录结构到仓库中查找
file->new->modul
如果你执行上述操作的时候是选择在hello上的话,也就是我们刚刚的模块,新生成的就会默认是之前的子包,如果你选择不是在子包上的话,默认就没有依赖关系
添加依赖
从这里可以查看我们刚刚的依赖
注意想要运行我们有依赖关系的模块的话,需要保证所依赖的模块在仓库中是有的。如果本地仓库删了,就要将之前的依赖的文件重新打包和安装
如果A依赖B,B依赖C,那么A->B和B->C都是直接依赖,而A->C是间接依赖
1.compile(默认就是这个范围)
(1)main目录下的Java代码可以访问这个范围的依赖
(2)test目录下的Java代码可以访问这个范围的依赖
(3)部署到TOMCAT服务器上运行时要放在WEB-INF的lib目录下
2.test
(1)main目录下的Java代码不能访问这个范围的依赖
(2)test目录下的Java代码可以访问这个范围的依赖
(3)部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下
3.provided
(1)main目录下的Java代码可以访问这个范围的依赖
(2)test目录下的Java代码可以访问这个范围的依赖
(3)部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下
默认不写就是compile的依赖范围。
如果是compile,就意味着这个hello程序下的main和test都能访问到这个Junit包,并且由于我们部署到服务器上的是主程序,所以部署到TOMCAT服务器上运行时要放在WEB-INF的lib目录下
如果是test的话就只有test中的代码才能够访问,注意,我们在部署程序到服务器上的时候是不将测试程序部署上去的,只会将主程序部署上去,所以部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下
provided为什么不会放在WEB-INF的lib目录下,因为这个provided是提供的jar包范围,也就是说我们的Tomcat服务器会提供给我们的项目的,不用导入这个包了。
compile范围的依赖是可以在我们的依赖链中进行传递的。
Maven工程 | 依赖范围 | 对A的可见性 | ||
A | B | C | compile | √ |
D | test | × | ||
E | provided | × |
比方说A依赖于B,B依赖于MySQL的包,然后顺着这条依赖链,A也依赖于MySQL,在A中也可以使用MySQL的包。
这里我们依赖了一个log4j包
然后我们会看到它自动就将这个log4j包传递给了依赖于hello的hellofriend模块
下面的图中hellofriend比hello更近,就用hellofriend的包
再创建一个makefriend依赖于hellofriend
当前由于是compile的依赖链所以都是相同的
这里我们将hellofriend中的log4j版本改成1.2.17版本
这里我们hellofriend的模块时1.12.17,我们ourfriend中的模块时1.12.16,然后makefriend同时依赖于这两个模块,但是先依赖hellofriend模块,后依赖ourfriend 模块
结果发现makefriend所使用的是我们先声明的hellofriend模块中的1.12.17的版本
如果我们在当前工程中引入了一个依赖是 A,而 A 又依赖了 B,那么 Maven 会自动将 A 依赖的 B 引入当前工程,但是个别情况下 B 有可能是一个不稳定版,或对当前工程有不良影响。 这时我们可以在引入 A 的时候将 B 排除。
现在在hello模块里有一个log4j 1.12.14,然后hellofriend依赖于log4j,所以这个log4j包会传递过去,但是如果我现在不像让它传递过来,就需要用到依赖的排除
在hellofriend依赖hello的位置进行排除,这个版本可以不写,将全部的版本都排除掉
对同一个框架的一组 jar 包最好使用相同的版本。为了方便升级框架,可以将 jar 包的版本信息统一提取出来
现在我们用的都是4.0.0的版本,如果我们想要统一改成别的版本就非常麻烦,要一个个去改
我们可以定义一个用于存储版本的变量
然后下面要使用版本号的地方用${版本号}的形式传入我们的版本号
那我们只需要修改变量就可以对下面所有的版本号进行统一修改了
如果我们现在修改成了5.1.7的版本,就能够马上全部修改了。
分类
[1]本地仓库:为当前本机电脑上的所有 Maven 工程服务。
[2]远程仓库
(1)私服:架设在当前局域网环境下,为当前局域网范围内的所有 Maven 工程服务。(2)中央仓库:架设在 Internet 上,为全世界所有 Maven 工程服务。
(3)中央仓库的镜像:架设在各个大洲,为中央仓库分担流量。减轻中央仓库的压力,同时更快的响应用户请求。
仓库中的文件
[1]Maven 的插件
[2]我们自己开发的项目的模块
[3]第三方框架或工具的 jar 包
不管是什么样的 jar 包,在仓库中都是按照坐标生成目录结构,所以可以通过统一的方式查询或依赖。
什么是 Maven 的生命周期?
●Maven 生命周期定义了各个构建环节的执行顺序,有了这个清单, Maven 就可以自动化的执行构建命令了。
●Maven 有三套相互独立的生命周期, 分别是:
①Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
②Default Lifecycle 构建的核心部分,编译,测试,打包,安装,部署等等。
③Site Lifecycle 生成项目报告,站点,发布站点。
它们是相互独立的,你可以仅仅调用 clean 来清理工作目录,仅仅调用 site 来生成站点。 当然你也可以直接运行 mvn clean install site 运行所有这三套生命周期。
每套生命周期都由一组阶段(Phase)组成,我们平时在命令行输入的命令总会对应于一个特定的阶段。比如,运行 mvn clean,这个 clean 是 Clean 生命周期的一个阶段。有 Clean 生命周期,也有 clean 阶段。
Clean 生命周期
Clean 生命周期一共包含了三个阶段:
①pre-clean 执行一些需要在 clean 之前完成的工作
②clean 移除所有上一次构建生成的文件
③post-clean 执行一些需要在 clean 之后立刻完成的工作
Site 生命周期
①pre-site 执行一些需要在生成站点文档之前完成的工作
②site 生成项目的站点文档
③post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
④site-deploy 将生成的站点文档部署到特定的服务器上
这里经常用到的是 site 阶段和 site-deploy 阶段,用以生成和发布 Maven 站点,这可是 Maven 相当强大的功能, Manager 比较喜欢,文档及统计数据自动生成,很好看。
Default 生命周期
Default 生命周期是 Maven 生命周期中最重要的一个,绝大部分工作都发生在这个生命周期中。这里,只解释一些比较重要和常用的阶段:
validate
generate-sources
process-sources generate-resources
process-resources 复制并处理资源文件,至目标目录,准备打包。
compile 编译项目的源代码。
process-classes
generate-test-sources
process-test-sources
generate-test-resources
process-test-resources 复制并处理资源文件,至目标测试目录。
test-compile 编译测试源代码。
process-test-classes
test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署。
prepare-package
package 接受编译好的代码,打包成可发布的格式,如 JAR。
pre-integration-test
integration-test
post-integration-test
verify
install 将包安装至本地仓库,以让其它项目依赖。
deploy 将最终的包复制到远程的仓库,以让其它开发人员与项目共享或部署到服务器上运行。
compile
test
package
也就是说每次都是从生命周期的开始执行到指定的位置。所以我们如果要package的话,不必手动执行前面的步骤,Maven会自动运行的。
生命周期与自动化构建
运行任何一个阶段的时候,它前面的所有阶段都会被运行, 例如我们运行 mvn install 的时候,代码会被编译,测试,打包。 这就是 Maven 为什么能够自动执行构建过程的各个环节的原因。此外, Maven 的插件机制是完全依赖 Maven 的生命周期的,因此理解生命周期至关重要。
●Maven 的核心仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的。
●每个插件都能实现多个功能,每个功能就是一个插件目标。
●Maven 的生命周期与插件目标相互绑定,以完成某个具体的构建任务。
例如: compile 就是插件 maven-compiler-plugin 的一个目标; pre-clean 是插件 maven-clean-plugin 的一个目标。
刚刚我们的编译,测试,打包等等操作都是交给对应的插件去完成的。
从一个插件可以完成多个功能,如下面的主程序的编译和测试程序的变异都是交给maven-compiler-plugin去完成的,这个插件想要完成的功能就称为这个插件的目标,也就是这个插件存在的意义。