Maven 的常用命令
mvn compile 编译,将Java 源程序编译成 class 字节码文件。 mvn test 测试,并生成测试报告 mvn clean 将以前编译得到的旧的 class 字节码文件删除 mvn pakage 打包,动态 web工程打 war包,Java工程打 jar 包。 mvn install 将项目生成 jar 包放在仓库中,以便别的模块调用
compile:将Java 源程序编译成 class 字节码文件。
第一步:选择 pom.xml 文件,右键--->Run As ---->2 Maven build...
第二步:在第一步执行完后弹出来的对话框中,输入 compile,然后点击 Run 按钮
第三步:查看控制台
第四步:在 target 目录下,我们会发现编译生成的 class 文件
test:测试,并生成测试报告
- 第一步:选择 pom.xml 文件,右键--->Run As ---->2 Maven build...,然后在弹出框中输入 test,或者选择 pom.xml 文件,右键--->Run As------>6 Maven test
- 第二步:查看控制台,分析测试程序,我们传入的参数是Tom,而我们希望的是maven,很显然是不相等的,那么测试失败
如果测试类 HelloTest.java改为如下:
重新执行 mvn test 命令,控制台如下:
生成的测试报告可以在如下目录查看:target/surefire-reports
mvn clean 将以前编译得到的旧的 class 字节码文件删除
- 第一步:选择 pom.xml 文件,右键--->Run As ---->2 Maven build...,然后在弹出框中输入 clean
或者选择 pom.xml 文件,右键--->Run As------>3 Maven clean,如下图
- 第二步:查看控制台
- 第三步:发现 mvn compile 编译好的文件这时已经清除了
mvn pakage 打包,动态 web工程打 war包,Java工程打 jar 包。
- 第一步:选择 pom.xml 文件,右键--->Run As ---->2 Maven build...,然后在弹出框中输入 package
- 第二步:查看控制台
- 第三步:进入到 target 目录,会发现打出来的 jar 包
mvn install 将项目生成 jar 包放在仓库中,以便别的模块调用
Maven 坐标的概念和依赖管理
我们知道 maven 能帮我们管理jar包,那么它是怎么管理的呢?我们下面就来讲解一下
什么是坐标
「数学中的坐标」
在平面上,使用 X 、Y 两个向量可以唯一的定位平面中的任何一个点
在空间中,使用 X、Y、Z 三个向量可以唯一的定位空间中的任意一个点
「Maven 中的坐标」
俗称 gav:使用下面三个向量子仓库中唯一定位一个 Maven 工程
在项目中的 pom.xml 文件中,我们可以看到下面 gav 的定义
- groupid:公司或组织域名倒序 :com.ys.maven
- artifactid:模块名,也是实际项目的名称:Maven_05
- version:当前项目的版本:0.0.1-SNAPSHOT
「Maven 坐标和仓库,jar 包的关系」
什么是仓库,后面我们会详细讲解,现在你只需要知道是 Maven 用来存放 jar 包的地方。
那么依照上面定义的 gav,我们执行 mvn -install 命令,会出现什么情况呢?
首先进入到我们上面讲过的 settings.xml 文件配置的仓库目录。
将我们上面配置的 gav 向量组合起来就是目录:
com/ys/maven/Maven_05/0.0.1-SNAPSHOT/Maven_05-0.0.1-SNAPSHOT.jar
其次,我们观察打出来的 jar 包:Maven_05-0.0.1-SNAPSHOT.jar,也就是 artifactid-version.jar
Maven 依赖
什么是依赖
?相信有过一定开发经验的人知道,每当我们需要使用某个框架时,比如 SpringMVC,那么我们需要导入相应的 jar 包,但是手动导入包的时候,往往会漏掉几个 jar 包,那么在使用该框架的时候系统就会报错。那么我们就说导入的包与未导入的包存在依赖关系。而使用 Maven,我们只需要在 pom.xml 文件中进行相应的配置,它就会帮助我们自动管理 jar 包之间的依赖关系。那么它是怎么管理的呢,接下来我们会详细讲解。
依赖的详细配置
我们以 Junit 为例,在 pom.xml 文件中进行详细而完整的配置。
<project> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <type>...</type> <scope>...</scope> <optional>...</optional> <exclusions> <exclusion> <groupId>...</groupId> <artifactId>...</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </project>
- dependencies:一个 pom.xml 文件中只能存在一个这样的标签。用来管理依赖的总标签。
- dependency: 包含在 dependencies 标签中,可以有无数个,每一个表示一个依赖
- groupId、artifactId 和 version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven根 据坐标才能找到需要的依赖。
- type:依赖的类型,对应于项目坐标定义的 packaging。大部分情况下,该元素不必声明,其默认值是 jar。
- scope:依赖的范围,默认值是 compile。后面会进行详解。
- optional:标记依赖是否可选。
- exclusions:用来排除传递性依赖,后面会进行详细介绍。
依赖的范围 scope
先放一张图
一般情况下,我们对前面三个依赖用的比较多。下面的主程序表示 maven 目录结构 src/main/java.测试程序目录结构为:src/test/java
「compile 范围依赖」
对主程序是否有效:有效
对测试程序是否有效:有效
是否参与打包:参与
是否参与部署:参与
典型例子:log4j
「test 范围依赖」
对主程序是否有效:无效
对测试程序是否有效:有效
是否参与打包:不参与
是否参与部署:不参与
典型例子:Junit
「provided 范围依赖」
对主程序是否有效:有效
对测试程序是否有效:有效
是否参与打包:不参与
是否参与部署:不参与
典型例子:servlet-api.jar,一般在发布到 服务器中,比如 tomcat,服务器会自带 servlet-api.jar 包,所以provided 范围依赖只在编译测试有效。
「runtime 范围依赖」:在测试、运行的时候依赖,在编译的时候不依赖。例如:JDBC 驱动,项目代码只需要 jdk 提供的 jdbc 接口,只有在执行测试和运行项目的时候才需要实现 jdbc 的功能。
接下来我们举几个例子在工程中实际去理解:
「test 依赖和 compile 依赖的区别:」
首先我们在 pom.xml 文件中配置,Junit 的 test 依赖
我们在主程序中去导入 Junit 的包,然后进行 mvn -compile 编译,很明显,test 范围的在主程序中无效,故编译会报错。
我们在 src/main/java 包下新建 MavenTest.java,并导入 Junit 包
然后执行 mvn -compile 操作,如下图报错信息:
我们将 Junit 的依赖范围改为 compile,然后执行 mvn -compile
发现 mvn -compile 没有报错了。
依赖的传递
比如我们创建三个 Maven 工程,maven-first,maven-second 以及 maven-third,而 third 依赖于 second,second 又依赖于 first,那么我们说 second 是 third 的第一直接依赖,first 是 second 的第二直接依赖。而 first 是 third 的间接依赖。
依赖之间的传递如下图:「第一列表示第一直接依赖,第一行表示第二直接依赖」
总结
当第二依赖的范围是 compile
的时候,传递性依赖的范围与第一直接依赖的范围一致。
当第二直接依赖的范围是 test
的时候,依赖不会得以传递。
当第二依赖的范围是 provided
的时候,只传递第一直接依赖范围也为provided
的依赖,且传递性依赖的范围同样为 provided;
当第二直接依赖的范围是 runtime
的时候,传递性依赖的范围与第一直接依赖的范围一致,但compile
例外,此时传递的依赖范围为 runtime;
我们这里举个例子来看:
第二依赖范围是 test
Maven_first 的pom.xml 文件如下:
然后 Maven_second 依赖 Maven_fisrt,Maven_third 依赖 Maven-second,其pom.xml 文件如下
Maven_second的 pom.xml
Maven_third 的 pom.xml
我们发现在 Maven_third 和 Maven_second 都没有 Maven_first 引入的 Junit 包,正好符合上面总结的第二点:当第二直接依赖的范围是test的时候,依赖不会得以传递。
第二依赖范围是 compile
如果我们将 Maven_first 的Junit 改为 compile,那么将会符合上面总结的第一点:当第二依赖的范围是compile的时候,传递性依赖的范围与第一直接依赖的范围一致。