Maven 的应用与实战
主要内容
Maven 简介
Maven 的下载与 IDE 的整合
Maven 仓库与配置
Maven 工程类型
在 Idea 中创建 Maven 工程
Maven 项目结构
POM 模型
Maven 中的常见插件
Maven 常用命令
Maven 项目命名规范
搭建 Maven 私服
基于 Maven 创建 war 工程
Maven 实战
Tomcat 热部署
学习目标
一、 Maven 简介
1 什么是 Maven
目前无论使用 IDEA 还是 Eclipse 等其他 IDE,使用里面 ANT 工具。ANT 工具帮助我
们进行编译,打包运行等工作。
Apache 基于 ANT 进行了升级,研发出了全新的自动化构建工具 Maven。(知道:
ANT 有的功能 MAVEN 都有,只是使用起来更加方便了)。
Maven 工具基于 POM(Project Object Model,项目对象模型)模式实现的。在 Maven
中每个项目都相当于是一个对象,对象(项目)和对象(项目)之间是有关系的。关系包含
了:依赖、继承、聚合,实现 Maven 项目可以更加方便的实现导 jar 包、拆分项目等效果。
Maven 是跨平台的,这意味着无论是在 Windows 上,还是在 Linux 或者 Mac 上,
都可以使用同样的命令。
Maven 还有一个优点,它能帮助我们标准化构建过程。在 Maven 之前,十个项目可
能有十种构建方式。有了 Maven 之后,所有项目的构建命令都是标准化。
Maven 还为全世界的 Java 开发者提供了一个免费的中央仓库,在其中几乎可以找到
任何的流行开源类库。
2 Maven 的作用
**1)**Maven 统一集中管理好所有的依赖包,不需要程序员再去寻找。对应第三方组件用到的共同 jar,Maven 自动解决重复和冲突问题。
**2)**Maven 作为一个开放的架构,提供了公共接口,方便同第三方插件集成。程序员可以将自己需要的插件,动态地集成到 Maven,从而扩展新的管理功能。
**3)**Maven 可以统一每个项目的构建过程,实现不同项目的兼容性管理。
二、 Maven 的下载与 IDE 的整合
3 Maven 下载
http://maven.apache.org/download.cgi
4 Idea 整合 Maven
在 Idea 中默认已经整合了 Maven。由于 Idea 的版本不同,所整合的 Maven 的版本也不同。
如果需要更换其他版本可在 Idea 中进行配置。
三、 Maven 仓库与配置
1 Maven 仓库是什么
1.1 Maven 仓库
Maven 仓库是基于简单文件系统存储的,集中化管理 Java API 资源(构件)的一个服
务。仓库中的任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存
储路径,这要得益于 Maven 的坐标机制,任何 Maven 项目使用任何一个构件的方式都
是完全相同的,Maven 可以在某个位置统一存储所有的 Maven 项目共享的构件,这个统
一的位置就是仓库,项目构建完毕后生成的构件也可以安装或者部署到仓库中,供其它项目
使用。
坐标:坐标有三个部分构成,如果一个部分不同那么表示的就是不同的 jar。
Group Id: 公司名,多用公司网址倒写
Artifact Id: 项目名
Version: 版本
对于 Maven 来说,仓库分为两类:本地仓库和中央仓库。
1.1.1 中央仓库
中央仓库是互联网上的服务器,是 Maven 提供的最大的仓库,里面拥有最全的 jar 包资
源。默认是 Maven 自己的网络服务器,但是由于访问速度较慢,我们一般都配置成国内的
镜像中央仓库如阿里镜像或者是华为镜像。
Maven 中央仓库访问页面: https://mvnrepository.com/
1.1.2 本地仓库
本地仓库指用户电脑中的文件夹,该文件夹中包含了自己下载的构件(jar 包)。文件夹结
构为 groupid 分级的文件夹/artifactid 文件夹/version 文件夹/包含 jar 包。
2 仓库的访问优先级
2.1 本地仓库
第一访问本地仓库。
2.2 远程仓库
2.2.1镜像仓库
镜像仓库是 Maven 开发过程中的首选远程仓库,在本地仓库无法获取资源的时候,直
接访问镜像仓库。
2.2.2 中央仓库
中央仓库是 Maven 官方提供的远程仓库,在本地仓库无法获取资源的时候,直接访问中央仓库。
3 配置 Maven
3.1 在 settings.xml 文件中配置本地仓库
本地仓库是开发者本地电脑中的一个目录,用于存储从远程仓库下载的构件(jar 包)。
默认的本地仓库是${user.home}/.m2/repository。用户可使用 settings.xml 文件修改本地
仓库。具体内容如下:
3.2 在 settings.xml 文件中配置镜像仓库
如果仓库 A 可以提供仓库 B 存储的所有内容,那么就可以认为 A 是 B 的一个镜像。例
如:在国内直接连接中央仓库下载依赖,由于一些特殊原因下载速度非常慢。这时,我们可
以使用阿里云提供的镜像 http://maven.aliyun.com/nexus/content/groups/public/来
替换中央仓库 http://repol.maven.org/maven2/。修改 maven 的 setting.xml 文件,具
体内容如下:
<mirror>
<!-- 指定镜像 ID -->
<id>nexus-aliyun</id>
<!-- 匹配中央仓库。-->
<mirrorOf>central</mirrorOf>
<!-- 指定镜像名称 -->
<name>Nexus aliyun</name>
<!-- 指定镜像路径 -->
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
3.3 配置 JDK 版本
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
四、 Maven 工程类型
1 POM 工程
POM 工程是逻辑工程(maven不会对pom工程做打包处理)。用在聚合工程中,或者父级工程用来做 jar 包的版本控制。
2 JAR 工程
创建一个 Java Project,在打包时会将项目打成 jar 包。
3 WAR 工程
创建一个 Web Project,在打包时会将项目打成 war 包。
五、 在 Idea 中创建 Maven 工程
如果未指定项目类型默认为Jar 类型
六、 Maven 项目结构
src 包含了项目所有的源代码和资源文件以及测试代码。
src/main/java 这个目录下储存 java 源代码
src/main/resources 储存主要的资源文件。比如 spring 的 xml 配置文件和 log4j 的 properties 文件。
src/test/java 存放测试代码,比如基于 JUNIT 的测试代码一般就放在这个目录下面
target 编译后内容放置的文件夹 ,项目被maven打包之后 jar 包也会被放到这
pom.xml 是 Maven 的基础配置文件,也是 Maven 项目核心配置文件,用于配置项目的基本信息,项目的继承关系,项目类型,依赖管理,依赖注入,插件管理,插件 注入等等
–mavenDemo 项目名 |
---|
–.idea 项目的配置,自动生成的,不需要关注。 |
–src |
– main 实际开发内容 |
–java 写包和 java 代码,此文件默认只编译.java 文件 |
–resource 所有配置文件。最终编译把配置文件放入到 classpath 中。 |
– test |
–java 测试时使用,自己写测试类或 junit 工具等 |
pom.xml 整个 maven 项目所有配置内容。 |
七、 POM 模型
1 依赖关系
Maven 一个核心的特性就是依赖管理。当我们处理多模块的项目(包含成百上千个模 块或者子项目),模块间的依赖关系就变得非常复杂,管理也变得很困难。针对此种情形, Maven 提供了一种高度控制的法。
通俗理解:依赖谁就是将谁的 jar 包添加到本项目中。可以依赖中央仓库的 jar,也可 以依赖当前开发中其他项目打包后的 jar 包。 (可以依赖第三方的也可以依赖我自己的项目但是前提是被依赖的项目也是一个Maven项目,只有Maven项目才有坐标的概念)
在 pom.xml 文件 根元素 project 下的 dependencies 标签中,配置依赖信息,可以 包含多个 dependence 元素,以声明多个依赖。每个依赖 dependence 标签都应该包含 以下元素:groupId, artifactId, version : 依赖的基本坐标, 对于任何一个依赖来说,基 本坐标是最重要的, Maven 根据坐标才能找到需要的依赖。
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
</dependencies>
1.1 依赖的传递性
依赖传递性是 Maven2.0 的新特性。假设你的项目依赖于一个 jar 包,而这个 jar 包又 依赖于其他 jar 包。你不必自己去找出所有这些依赖,你只需要加上你直接依赖的 jar 包的 坐标,Maven 会隐式的把这些 jar 包间接依赖的库也加入到你的项目中。这个特性是靠解 析从远程仓库中获取的依赖 jar 包的项目文件实现的。这些项目的所有依赖都会加入到项目 中这就是依赖传递性。
如果 A 依赖了 B,那么 C 依赖 A 时会自动把 A 和 B 都导入进来。
创建 A 项目后,选择 IDEA 最右侧 Maven 面板 lifecycle,双击 install 后就会把项目 安装到本地仓库中,其他项目就可以通过坐标引用此项目。
如果依赖的是自己的项目一定要对自己的项目进行打包处理,打包是为了让项目出现在本地仓库中,在本地仓库中包含了它所对应的jar 包,这样Maven 才能把这个 jar 包依赖到其他项目中
被打包进了本地仓库
1.2 依赖相同资源的依赖原则
1.2.1 第一原则:最短路径优先原则
“最短路径优先”意味着项目依赖关系树中路径最短的版本会被使用。例如,假设 A、 B、C 之间的依赖关系是 A->B->C->D(2.0)和 A->E->(D1.0),那么 D(1.0)会被使用,因为 A 通过 E 到 D 的路径更短。
A->B : A 依赖 B
1.2.2 第二原则:最先声明原则
依赖调解第一原则不能解决所有问题,比如这样的依赖关系:A–>B–>Y(1.0),A–>C –>Y(2.0),Y(1.0)和 Y(2.0)的依赖路径长度是一样的,都为 2。那么到底谁会被解析使用呢?
在 maven2.0.8 及之前的版本中,这是不确定的,但是 maven2.0.9 开始,为了尽可能避免 构建的不确定性,maven 定义了依赖调解的第二原则:第一声明者优先。在依赖路径长度 相等的前提下,在 POM 中依赖声明的顺序决定了谁会被解析使用。顺序最靠前的那个依赖 优胜。
1.3 排除依赖
exclusions: 用来排除传递性依赖 其中可配置多个 exclusion 标签,每个 exclusion 标签 里面对应的有groupId, artifactId 两项基本元素。
EG:我不想要 spring-context 里面的 spring-aop jar 包
未排除 spring-aop 时这个jar 包还在
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.4.RELEASE</version>
<exclusions>
<!--在导入spring-context依赖时去掉spring-aop-->
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
排除之后 spring-aop 这个jar 包不在了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rWhFwcbi-1607514135828)(Maven.assets/image-20201119110846898.png)]
可以通过 标签排除依赖,如果spring-aop 这个jar 已经被 spring-context 包含了,这个时候无法通过 排除依赖的, 只能排除依赖不能排除被包含的jar 包
1.4 依赖范围
1.4.1scope 属性可取值
1.4.1.1compile
这是默认范围。如果没有指定,就会使用该依赖范围。表示该依赖在编译和运行时生效。 在项目打包时会将该依赖包含进去。
1.4.1.2provided
可以参与编译,测试,运行等周期,但是不会被打包到最终的 artifact 中。典型的例子 是 servlet-api,编译和测试项目的时候需要该依赖,但在项目打包的时候,由于容器已经 提供,就不需要 Maven 重复地引入一遍(如:servlet-api)
1.4.1.3runtime
runtime 范围表明编译时不需要生效,而只在运行时生效。典型的例子是 JDBC 驱动实 现,项目主代码的编译只需要 JDK 提供的 JDBC 接口,只有在执行测试或者运行项目的时 候才需要实现上述接口的具体 JDBC 驱动。
1.4.1.4system
如果有些你依赖的 jar 包没有 Maven 坐标的(非maven项目),它完全不在 Maven 体系中,这时候你 可以把它下载到本地硬盘,然后通过 system 来引用。
不推荐使用 system,因为一个项目的 pom.xml 如果使用了 scope 为system 的 depend 后,会导致传递依赖中断,即所有其他依赖本项目的项目都无法传递依赖了。
1.4.1.5test
test 范围表明使用此依赖范围的依赖,只在编译测试代码和运行测试的时候需要,应用 的正常运行不需要此类依赖。典型的例子就是 JUnit,它只有在编译测试代码及运行测试的 时候才需要。
1.5 依赖管理
Maven 提 供 了 一 个 机 制 来 集 中 管 理 依 赖 信 息 , 叫 做 依 赖 管 理 元 素 ” ”。假设你有许多项目继承自同一个公有的父项目,那可以 把所有依赖信息放在一个公共的 POM 文件中并且在子 POM 中简单的引用该构件即可。
标签下所有的的依赖只是做到了集中式管理并不是添加到项目中
右侧的 dependency 标记都没了 并没有任何依赖注入到项目中
一般配合 标签使用,一般在 标签内定义集中管理依赖的版本
把依赖的版本放到外部管理
2 继承关系
2.1 什么是继承关系
Maven 中的继承跟 Java 中的继承概念一样,需要有父项目以及子项目。我们可以将项 目中的依赖和插件配置提取出来在父项目中集中定义,从而更方便的管理项目的依赖以及插 件。
注意父项目类型一定为 POM 类型。
2.2 继承的优点
1) 依赖或插件的统一管理(在 parent 中定义,需要变更 dependency 版本时,只需要 修改一处)。
2) 代码简洁(子 model 只需要指定 groupId,artifactId 即可)。
3) dependencyManagement 是 “ 按 需 引 入 ” , 即 子 model 不 会 继 承 parent 中 dependencyManagement 所有预定义的 dependency。
一旦两个项目有了父子继承关系在子项目在引入依赖时不需要 version
在继承关系中 标签下的所有内容是不会都被子项目继承,按需分配,子项目中定义的会被添加,未定义的不添加
父项目中管理了 spring-web
而子项目中未定义 spring-web 所以子项目不会引入 spring-web
父项目在版本改变后需要 install 安装一下
在子项目中刷新一下,子项目中的依赖版本也变为 4.2.4版 父项目下所有的子项目的依赖版本都会跟着改变
3 Maven 中的多继承
在 Maven 中对于继承采用的也是单一继承,也就是说一个子项目只能有一 个父项目,但是有的时候我们项目可能需要从更多的项目中继承,那么我们可以 在子项目中通过添加标记来实现多继承。在子项 目的中每个标记就一个父工程 定义,同时还需要添加标记,值为 pom。添加标记,值为 import。
child 工程即从 parent 工程继承 也从 parent_b 工程(基于pom文件引入进来)继承
第一种方式用 标签和 标签
parent/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjsxt</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!--指定项目类型为pom-->
<packaging>pom</packaging>
<!--对依赖进行集中式管理-->
<properties>
<spring-context.version>5.2.4.RELEASE</spring-context.version>
<spring-web.version>5.2.4.RELEASE</spring-web.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-context.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-web.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
parent_b/xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjsxt</groupId>
<artifactId>parent_b</artifactId>
<version>1.0-SNAPSHOT</version>
<!--指定项目类型为 pom-->
<packaging>pom</packaging>
<properties>
<spring-web.version>5.2.4.RELEASE</spring-web.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-web.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
chile/xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bjsxt</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<groupId>com.bjsxt</groupId>
<artifactId>child</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>parent_b</artifactId>
<version>1.0-SNAPSHOT</version>
<!--type 的值必须是 pom-->
<type>pom</type>
<!--scope 的值必须是 import-->
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
</dependencies>
</project>
第二种方式,只用 标签实现
parent/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjsxt</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!--指定项目类型为pom-->
<packaging>pom</packaging>
<!--对依赖进行集中式管理-->
<properties>
<spring-context.version>5.2.4.RELEASE</spring-context.version>
<spring-web.version>5.2.4.RELEASE</spring-web.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-context.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-web.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
parent_b/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjsxt</groupId>
<artifactId>parent_b</artifactId>
<version>1.0-SNAPSHOT</version>
<!--指定项目类型为 pom-->
<packaging>pom</packaging>
<properties>
<spring-web.version>5.2.4.RELEASE</spring-web.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-web.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
child/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjsxt</groupId>
<artifactId>child</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>parent_b</artifactId>
<version>1.0-SNAPSHOT</version>
<!--type 的值必须是 pom-->
<type>pom</type>
<!--scope 的值必须是 import-->
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
</dependencies>
</project>
bug:
idea 会时不时的自己将Maven 本地仓库的位置改变成默认的,导致以上错误,每次创建项目之后检查本地仓库的位置是否改变
4 聚合关系
Maven 的聚合特性可以帮助我们把多个项目基于多个模块聚合在一起,这样能够更加 方便项目的管理。
前提:继承。
项目的聚合是建立在继承的关系上的,聚合包含了继承的特性。
聚合时多个项目的本质还是一个项目。这些项目被一个大的父项目包含。且这时父项目 类型为 pom 类型。同时在父项目的 pom.xml 中出现表示包含的所有子模块。 即使在 idea 中,也可以使用聚合在一个窗口创建多个项目。
用一个parent将其他的模块做一个集中式管理
parent/pom.xml 发生变化 每一个 标签表示一个聚合进来的模块 每聚合进来的一个模块就表示一个独立的项目
parent./pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjsxt</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>aggredemo</module>
</modules>
<!--指定项目类型为pom-->
<packaging>pom</packaging>
<properties>
<spring-web.version>5.2.4.RELEASE</spring-web.version>
</<