Maven基本使用
Maven命令
运行 Maven 中和构建操作相关的命令时,必须进入到 pom.xml 所在的目录。
而构建相关的命令要在 pom.xml 所在目录下运行——操作哪个工程,就进入这个工程的 pom.xml 目录。
API | 作用 |
---|---|
mvn clean | 删除 target 目录 |
mvn compile | 主程序编译 结果存放到target/classes |
mvn test-compile | 测试程序编译 结果存放到target/test-classes |
mvn test | 测试操作 测试的报告存放的目录:target/surefire-reports |
mvn package | 打包的结果–jar 包 存放的目录:target |
mvn install | 安装操作 |
安装的效果是将本地构建过程中生成的 jar 包存入 Maven 本地仓库。这个 jar 包在 Maven 仓库中的路径是根据它的坐标生成的。
坐标信息如下:
<groupId>com.atguigu.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
在 Maven 仓库中生成的路径如下:
D:\maven-rep1026\com\atguigu\maven\pro01-maven-java\1.0-SNAPSHOT\pro01-maven-java-1.0-SNAPSHOT.jar
另外,安装操作还会将 pom.xml 文件转换为 XXX.pom 文件一起存入本地仓库。所以我们在 Maven 的本地仓库中想看一个 jar 包原始的 pom.xml 文件时,查看对应 XXX.pom 文件即可,它们是名字发生了改变,本质上是同一个文件。
Maven中的坐标
[1]向量说明
使用三个『向量』 在『Maven的仓库』中唯一的定位到一个『jar』包。
- groupId:公司或组织的 id
- artifactId:一个项目或者是项目中的一个模块的 id
- version:版本号
[2]三个向量的取值方式
- groupId:公司或组织域名的倒序,通常也会加上项目名称
- 例如:com.atguigu.maven
- artifactId:模块的名称,将来作为 Maven 工程的工程名
- version:模块的版本号,根据自己的需要设定
- 例如:SNAPSHOT 表示快照版本,正在迭代过程中,不稳定的版本
- 例如:RELEASE 表示正式版本
坐标和仓库中 jar 包的存储路径之间的对应关系
坐标:
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
上面坐标对应的 jar 包在 Maven 本地仓库中的位置:
Maven本地仓库根目录\javax\servlet\servlet-api\2.5\servlet-api-2.5.jar
一定要学会根据坐标到本地仓库中找到对应的 jar 包。
pom.xml文件解读
<!-- 当前Maven工程的坐标 -->
<groupId>com.atguigu.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 当前Maven工程的打包方式,可选值有下面三种: -->
<!-- jar:表示这个工程是一个Java工程 -->
<!-- war:表示这个工程是一个Web工程 -->
<!-- pom:表示这个工程是“管理其他工程”的工程 -->
<packaging>jar</packaging>
<name>pro01-maven-java</name>
<url>http://maven.apache.org</url>
<properties>
<!-- 工程构建过程中读取源码时使用的字符集 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 当前工程所依赖的jar包 -->
<dependencies>
<!-- 使用dependency配置一个具体的依赖 -->
<dependency>
<!-- 在dependency标签内使用具体的坐标依赖我们需要的一个jar包 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!-- scope标签配置依赖的范围 -->
<scope>test</scope>
</dependency>
</dependencies>
Maven约定的目录结构
另外还有一个 target 目录专门存放构建操作输出的结果。
依赖的范围
标签的位置:dependencies/dependency/scope
标签的可选值:compile/test/provided/system/runtime/import
①compile 和 test 对比
main目录(空间) | test目录(空间) | 开发过程(时间) | 部署到服务器(时间) | |
---|---|---|---|---|
compile | 有效 | 有效 | 有效 | 有效 |
test | 无效 | 有效 | 有效 | 无效 |
主体业务功能需要用到的使用 compile 范围 默认就是这个
test: 辅助性质,不会参与服务器的部署。比如junit,只是在本地做个单元测试
②compile 和 provided 对比
main目录(空间) | test目录(空间) | 开发过程(时间) | 部署到服务器(时间) | |
---|---|---|---|---|
compile | 有效 | 有效 | 有效 | 有效 |
provided | 有效 | 有效 | 有效 | 无效 |
provided:服务器上有对应的依赖,不需要部署到服务器
③结论
compile:通常使用的第三方框架的 jar 包这样在项目实际运行时真正要用到的 jar 包都是以 compile 范围进行依赖的。比如 SSM 框架所需jar包。
test:测试过程中使用的 jar 包,以 test 范围依赖进来。比如 junit。
provided:在开发过程中需要用到的“服务器上的 jar 包”通常以 provided 范围依赖进来。比如 servlet-api、jsp-api。而这个范围的 jar 包之所以不参与部署、不放进 war 包,就是避免和服务器上已有的同类 jar 包产生冲突,同时减轻服务器的负担。说白了就是:“服务器上已经有了,你就别带啦!”
依赖的传递
概念
A 依赖 B,B 依赖 C,那么在 A 没有配置对 C 的依赖的情况下,A 里面能不能直接使用 C?
传递的原则
在 A 依赖 B,B 依赖 C 的前提下,C 是否能够传递到 A,取决于 B 依赖 C 时使用的依赖范围。
- B 依赖 C 时使用 compile 范围:可以传递
- B 依赖 C 时使用 test 或 provided 范围:不能传递,所以需要这样的 jar 包时,就必须在需要的地方明确配置依赖才可以。
依赖的排除
概念
当 A 依赖 B,B 依赖 C 而且 C 可以传递到 A 的时候,A 不想要 C,需要在 A 里面把 C 排除掉。而往往这种情况都是为了避免 jar 包之间的冲突。
所以配置依赖的排除其实就是阻止某些 jar 包的传递。因为这样的 jar 包传递过来会和其他 jar 包冲突。
<dependency>
<!--通过指定被依赖工程的坐标完成依赖-->
<groupId>com.atguigu.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
<!--配置依赖的排除-->
<exclusions>
<!-- 配置具体排除信息,让 commons-logging不要传递到当前工程(pro02-maven-web)-->
<exclusion>
<!-- 这里指定坐标时不需要指定version -->
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
继承
1、概念
Maven工程之间,A 工程继承 B 工程
- B 工程:父工程
- A 工程:子工程
本质上是 A 工程的 pom.xml 中的配置继承了 B 工程中 pom.xml 的配置。
2、作用
在父工程中统一管理项目中的依赖信息,具体来说是管理依赖信息的版本。
它的背景是:
- 对一个比较大型的项目进行了模块拆分。
- 一个 project 下面,创建了很多个 module。
- 每一个 module 都需要配置自己的依赖信息。
它背后的需求是:
- 在每一个 module 中各自维护各自的依赖信息很容易发生出入,不易统一管理。
- 使用同一个框架内的不同 jar 包,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一。
- 使用框架时所需要的 jar 包组合(或者说依赖信息组合)需要经过长期摸索和反复调试,最终确定一个可用组合。这个耗费很大精力总结出来的方案不应该在新的项目中重新摸索。
通过在父工程中为整个项目维护依赖信息的组合既保证了整个项目使用规范、准确的 jar 包;又能够将以往的经验沉淀下来,节约时间和精力。
父工程配置
<groupId>com.atguigu.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 当前工程作为父工程,它要去管理子工程,所以打包方式必须是 pom -->
<packaging>pom</packaging>
只有打包方式为 pom 的 Maven 工程能够管理其他 Maven 工程。打包方式为 pom 的 Maven 工程中不写业务代码,它是专门管理其他 Maven 工程的工程。
添加模块工程后,父工程会自动配置聚合
<modules>
<module>pro04-maven-module</module>
<module>pro05-maven-module</module>
<module>pro06-maven-module</module>
</modules>
解读子工程的pom.xml
<!-- 使用parent标签指定当前工程的父工程 -->
<parent>
<!-- 父工程的坐标 -->
<groupId>com.atguigu.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<!-- 子工程的坐标 -->
<!-- 如果子工程坐标中的groupId和version与父工程一致,那么可以省略 -->
<!-- <groupId>com.atguigu.maven</groupId> -->
<artifactId>pro04-maven-module</artifactId>
<!-- <version>1.0-SNAPSHOT</version> -->
在父工程中配置依赖的统一管理
<!--在父工程中统一管理依赖信息-->
<!-- 注意:即使在父工程配置了对依赖的管理,子工程需要使用具体哪一个依赖还是要明确配置。-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
</dependencyManagement>
子工程中引用那些被父工程管理的依赖
<!-- 子工程引用父工程中的依赖信息时,可以把版本号去掉。 -->
<!-- 把版本号去掉就表示子工程中这个依赖的版本由父工程决定。 -->
<!-- 具体来说是由父工程的dependencyManagement来决定。 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<!--对于已经在父工程进行了管理的依赖,子工程中引用时可以不写version -->
<!-- <version>4.0.0.RELEASE</version> -->
<!-- 情况 1 确实省略了version标签:子工程采纳的就是父工程管理的版本-->
<!-- 情况 2 没有省略version标签:
A: 这里配置了version和父工程管理的版本一致,最终还是采纳这个版本。
B: 这里配置了version
但是和父工程管理的版本不一致,那么这里子工程配置的版本会覆盖父工程管理的版本并最终采纳。
绝大部分情况下子工程还是遵从父工程统一管理的依赖。
-->
</dependency>
</dependencies>
在父工程中声明自定义属性
<!-- 通过自定义属性,统一指定Spring的版本 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--创建我们自定义的属性标签-->
<!--标签名:属性名-->
<!--标签值:属性值-->
<!--引用方式:${atguigu.spring. version}-->
<atguigu.spring.version>4.2.0.RELEASE</atguigu.spring.version>
</properties>
在需要的地方使用${}的形式来引用自定义的属性名:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<!-- 通过引用属性表达式设定版本号,这样版本号就成了一个动态值-->
<!--通过属性名解析后才知道具体是什么值。-->
<version>${atguigu.spring.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
真正实现“一处修改,处处生效”。
聚合
使用一个“总工程”将各个“模块工程”汇集起来,作为一个整体对应完整的项目。
- 项目:整体
- 模块:部分
TIP
概念的对应关系:
从继承关系角度来看:
- 父工程
- 子工程
从聚合关系角度来看:
- 总工程
- 模块工程
好处
-
一键执行 Maven 命令:很多构建命令都可以在“总工程”中一键执行。
以 mvn install 命令为例:Maven 要求有父工程时先安装父工程;有依赖的工程时,先安装被依赖的工程。我们自己考虑这些规则会很麻烦。但是工程聚合之后,在总工程执行 mvn install 可以一键完成安装,而且会自动按照正确的顺序执行(先安装总工程,然后按照依赖工程,最后安装被依赖工程)。
-
配置聚合之后,各个模块工程会在总工程中展示一个列表,让项目中的各个模块一目了然。
聚合的配置
在总工程中配置 modules 即可:
<modules>
<module>pro04-maven-module</module>
<module>pro05-maven-module</module>
<module>pro06-maven-module</module>
</modules>
Idea环境
创建父工程
1、创建一个maven项目
2、定义坐标
3、配置maven家目录
创建Java模块项目
1、右击父工程,创建module
2、创建
配置坐标
创建web模块项目
1、创建module工程
2、在pom.xml 中 修改 打包形式为war
<!-- web工程 要求打包形式为 war -->
<packaging>war</packaging>
3、修改工程结构
选择我们刚创建的module
设置 web.xml 在那个目录下
D:\idea\JavaWeb\pro02-maven-idea-parent\pro04-module-web\src\main\webapp\WEB-INF\web.xml
设置静态资源存放位置
D:\idea\JavaWeb\pro02-maven-idea-parent\pro04-module-web\src\main\webapp
点击 apply 和 ok 后,创建成功
在Idea中执行maven命令
直接执行
手动输入
回车即可看到效果
如果有需要,还可以给命令后面附加参数:
# -D 表示后面要附加命令的参数,字母 D 和后面的参数是紧挨着的,中间没有任何其它字符
# maven.test.skip=true 表示在执行命令的过程中跳过测试
mvn clean install -Dmaven.test.skip=true
在终端中打开
在IDEA中查看某个模块的依赖信息
工程导入
Maven工程除了自己创建的,还有很多情况是别人创建的。而为了参与开发或者是参考学习,我们都需要导入到 IDEA 中。下面我们分几种不同情况来说明:
直接使用 IDEA 打开工程目录即可
[1]工程压缩包
假设别人发给我们一个 Maven 工程的 zip 压缩包:maven-rest-demo.zip。从码云或GitHub上也可以以 ZIP 压缩格式对项目代码打包下载。
[2]解压
如果你的所有 IDEA 工程有一个专门的目录来存放,而不是散落各处,那么首先我们就把 ZIP 包解压到这个指定目录中。
[3]打开
只要我们确认在解压目录下可以直接看到 pom.xml,那就能证明这个解压目录就是我们的工程目录。那么接下来让 IDEA 打开这个目录就可以了。
[4]设置 Maven 核心程序位置
打开一个新的 Maven 工程,和新创建一个 Maven 工程是一样的,此时 IDEA 的 settings 配置中关于 Maven 仍然是默认值:
当然,为了避免麻烦,可以设置 新项目默认设置
模块导入
导入 Java 类型模块
[1]找到老师发的工程目录
[2]复制我们想要导入的模块目录
[3]粘贴到我们自己工程目录下
这个工程(project)是我们事先在 IDEA 中创建好的。
[4]在 IDEA 中执行导入
导入复制进来的module
点击apply 和 ok 即可
导入web module工程