准备资源:jdk1.8、apache-maven-3.6.3、idea2019.3.3
一、Maven概述
- 什么是Maven?
Maven是一款自动化构建工具,服务于Java平台的项目构建和依赖管理。 - 特点
(1) 方便添加第三方jar包
添加jar包的传统方式是将需要的jar包拷贝复制到项目下的lib目录中,这样做会让项目占用空间变的很大。Maven使用pom文件来维护项目需要使用的jar包,程序会根据pom中维护的依赖坐标自动从本地仓库加载并使用jar包。
(2) 方便获取第三方jar包
传统方式需要我们自己在上网查找jar包资源,下载到本地,然后添加到项目中。Maven中,我们只要将需要的jar包坐标写入pom文件中,Maven就会自动到外网的中心仓库中将jar包下载到本地仓库中。
(3) 自动处理jar包之间的依赖关系
当一个jar包依赖其他的jar包时,Maven会自动将所依赖的jar包从本地仓库导入,如果本地仓库不存在,就会从外网的中央仓库将依赖下载到本地,然后导入项目。
(4) 自动处理jar包之间的冲突关系
当两个或者更多个jar包都依赖同一种jar包,但是所依赖的jar包版本号不同的时候,Maven会自动去解决这种冲突关系。处理原则是:最短路径者优先和先声明者优先。
(5) 能够将一个项目拆分成多个模块
(6) 实现项目的分布式部署
二、Maven安装
-
安装配置Java:
(1)使用引导程序安装java1.8,记录安装目录
(2) 配置系统环境变量JAVA_HOME、PATH系统环境变量名 取值 例子 JAVA_HOME java安装目录 C:\Program Files\Java\jdk1.8.0_311 PATH 末尾添加:%JAVA_HOME%/bin %JAVA_HOME%/bin
-
安装配置Maven
(1) 解压Maven压缩包,记录解压位置
(2) 配置系统环境变量MAVEN_HOME、PATH系统环境变量名 取值 例子 MAVEN_HOME Maven解压位置根目录 D:\moudle\apache-maven-3.6.3 PATH 末尾添加:%MAVEN_HOME%/bin %MAVEN_HOME%/bin
(3) 配置本地仓库地址和外网中央仓库地址
用文本编辑器打开%MAVEN_HOME%/conf/settings.xml
,在settings
标签内第一行添加<localRepository> <!-- 本地仓库地址,jar包存放在本机的位置 --> D:\moudle\apache-maven-3.6.3\repository </localRepository>
找到
mirrors
标签,在标签内部添加<!-- 配置阿里云的中央仓库 --> <mirror> <id>alimaven</id> <name>aliyun</name> <url>https://maven.aliyun.com/repository/central</url> <mirrorOf>central</mirrorOf> </mirror>
-
验证安装是否成功
(1) 打开cmd窗口
(2) cmd窗口中输入:mvn -v
cmd打印上述输出,表示Java和Maven都安装成功。 -
与Idea集成
(1)打开idea
(2)Configure
-->Settings
(3)Build,Execution,Deployment
-->Build Tools
-->Maven
(4)设置Maven home directory
、User settings file
、Local repository
配置项名 解释 Maven home directory MAVEN_HOME User settings file %MAVEN_HOME%/conf/settings.xml Local repository 本地仓库位置
三、Maven核心概念
-
pom.xml文件:Project Object Model:项目对象模型。将Java工程的相关信息封装为对象作为便于操作和管理的模型。Maven工程的核心配置。
-
约定的目录结构,不能随意修改
-
坐标
(1)定义: jar包的唯一标识属性名 说明 例子 groupId 公司或者组织的域名倒序+项目名称 com.company.project-name artifactId 要引入的jar包所属项目的模块名称 moudle-name version 版本号 4.12
(2)如何通过坐标查找jar包?
将groupId
、artifactId
、version
三个向量连起来,以连起来的字符串作为目录结构到仓库中寻找,例如:<!--坐标--> <!--目录结构--> <groupId>com.company.project-name</groupId> <artifactId>moudle-name</artifactId> ==> com/company/project-name/moudle-name/4.12/moudle-name-4.12.jar <version>4.12</version>
-
依赖管理
(1) 概念:当A.jar需要使用B.jar中的类的时候,就说A依赖于B。
(2)依赖分类:
a. 直接依赖:A.jar直接使用C.jar中的类,此时A直接依赖于C;
b. 间接依赖:A.jar直接依赖于B.jar,B.jar直接依赖于C.jar,如果A.jar需要使用C.jar中的类时,此时就说A间接依赖于C;
(3)依赖范围:
需要配置插件为:<build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
依赖范围 解释 compile(全部编译) main目录下的Java代码可以访问这个范围下的依赖,会将该范围下的依赖也一并打入jar包 test(只用于测试) 只有test目录下的Java代码可以访问这个范围下的依赖,不会将该范围下的依赖一并打入jar包 provided(已由服务器提供) main和test目录下的Java代码都可以访问这个范围下的依赖,不会将改范围下的依赖一并打入jar包,这些依赖应该由运行jar包的服务器提供
使用方式为:
<dependencies> <!--依赖坐标,仅测试用,不打入jar包--> <dependency> <groupId>com.company.project-name</groupId> <artifactId>moudle-name</artifactId> <version>4.12</version> <scope>test</scope> <!--如果不写,默认是compile范围--> </dependency> </dependencies>
(4)依赖的传递性
当间接依赖的jar包使用compile
范围导入时,其他间接依赖该jar包的模块才能访问该jar包。例如:依赖关系 B引入C的依赖范围 C对A的可见性 compile 可见 A 依赖于 B 依赖于 C test 不可见 provided 不可见
(5)依赖原则 => 解决jar包冲突
a. 路径最短者优先
b. 先声明者优先
模块A的
pom.xml
文件中引入B和C的代码如果是:<dependencies> <!--C的依赖坐标,先被声明--> <dependency> ... </dependency> <!--B的依赖坐标--> <dependency> ... </dependency> </dependencies>
那么依赖关系为:
模块A的pom.xml
文件中引入B和C的代码如果是:<dependencies> <!--B的依赖坐标,先被声明--> <dependency> ... </dependency> <!--C的依赖坐标--> <dependency> ... </dependency> </dependencies>
那么依赖关系为:
(6)依赖的排除
当模块A依赖于B.jar(或者更多jar包)时,如果在A模块中不想引入B.jar(或者其他jar包)所依赖的其他jar包时,可以不引入B.jar(或者其他jar包)所依赖的其他jar包。
使用方式为:<dependencies> <!--B的依赖坐标--> <depedency> <groupId>com.company.project-name</groupId> <artifactId>B</artifactId> <version>1.0</version> <scope>compile</scope> <!--依赖排除,可以排除多个依赖--> <exclusions> <!--要排除的第一个依赖,不需要书写版本号,会将所有版本的指定依赖排除--> <exclusion> <groupId>com.company.project-name</groupId> <artifactId>moudle-name</artifactId> </exclusion> <!--其他要排除的依赖--> <exclusion>...</exclusion> <exclusion>...</exclusion> <exclusion>...</exclusion> ... </exclusions> </dependency> <!--重新指定排除的依赖 => 自定义--> <dependency> <groupId>com.company.project-name</groupId> <artifactId>moudle-name</artifactId> <version>2.2</version> <scope>compile</scope> </dependency> <!--其他重新指定排除的依赖--> <dependency>...</dependency> <dependency>...</dependency> <dependency>...</dependency> ... </dependencies>
(7)在一个模块中,统一指定版本号
有一些jar包必须联合使用,是一整套的,每个jar包的版本号最好相同,不然会出兼容性问题。但是当某一套jar包数量太多时,修改版本号不方便,此时就可以统一指定版本号。
pom.xml
文件中应如下配置:<!--当前模块的坐标信息--> ... <!--指定变量,用来存储版本号信息--> <properties> <!--自定义变量的标签名--> <spring-version>4.0.0.RELEASE</spring-version> <!--其他的自定义变量--> <A>...</A> <B>...</B> ... </properties> <!--引入的依赖--> <dependencies> <!--spring全家桶,统一指定版本号,使用 ${变量名} 来访问变量值--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <!--使用 ${变量名} 来访问变量值--> <version>${spring-version}</version> <!--等价于 <version>4.0.0.RELEASE</version> --> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <!--使用 ${变量名} 来访问变量值--> <version>${spring-version}</version> <!--等价于 <version>4.0.0.RELEASE</version> --> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <!--使用 ${变量名} 来访问变量值--> <version>${spring-version}</version> <!--等价于 <version>4.0.0.RELEASE</version> --> </dependency> </dependencies>
(8)仓库
a. 本地仓库:settings.xml
中配置的存放jar包的本机文件路径;
b. 远程仓库:远程仓库类型 说明 私服 架设在当前局域网环境下,为当前局域网范围内的所有Maven工程服务,修改localRepository 中央仓库 架设在Internet上,为全世界所有Maven工程服务 中央仓库镜像 架设在各个大洲,为中央仓库分担流量。减轻中央仓库的压力,同时更快的响应用户请求
(9)主要生命周期
完整的生命周期是:
clean
=>validate
=>compile
=>test
=>package
=>verify
=>install
=>site
=>deploy
生命周期 作用 clean 清除 compile clean + 中间的生命周期 + 编译main下的Java文件 test clean + 中间的生命周期 + 编译test下的Java文件,并执行 package clean + 中间的生命周期 + 打包 install clean + 中间的生命周期 + 将打好的jar包放在本地仓库中,放在本地仓库之后,就可以在其他模块的pom文件中引入该jar包
(11)插件
Maven生命周期的作用是由插件提供的功能,每个插件可能提供多个功能,比如:
complier
插件提供了三个功能。
四、继承
- 什么是继承
父模块统一管理依赖的版本号,所有子模块引入同一种依赖后,都使用父模块中声明的依赖版本号。 - 为什么使用继承
有一些依赖的依赖范围不需要为compile
,这些依赖一旦成为间接依赖,其他模块想要使用,就都需要单独配置,可以使用继承统一版本号,需要进行修改的时候,只需要修改父模块pom.xml
文件中维护的版本号即可。 - 配置方式
(1)手动配置:
a. 项目结构为:
b. 在parent
模块的pom.xml
文件中进行配置:<!--parent模块的坐标信息--> ... <!--设置parent不打jar包--> <packaging>pom</packaging> <!--管理依赖版本号--> <dependencyManagement> <!--所有由parent模块管理的依赖--> <dependencies> <!--第一个指定版本号的依赖--> <dependency> <!--所有的子模块都会引入版本号为4.12,依赖范围为test的junit依赖--> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!--其他需要统一指定版本号的依赖--> <dependency>...</dependency> <dependency>...</dependency> <dependency>...</dependency> ... </dependencies> </dependencyManagement>
c. 在子模块的pom.xml
文件中进行配置:
child1
模块的pom.xml
文件配置(child2
一样):
<!--child1模块的坐标信息-->
...
<!--声明父模块-->
<parent>
<groupId>com.company.project-name</groupId>
<artifactId>parent</artifactId>
<version>1.0<version>
<!--parent模块中pom.xml文件的相对路径,相对当前模块的pom.xml文件-->
<relativePath>../parent/pom.xml</relativePath>
</parent>
<!--引入依赖-->
<dependencies>
<!--引入在parent模块中统一指定版本号的依赖,只需要写groupId和artifactId就可以了-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<!--其他的一些依赖-->
<dependency>...</dependency>
<dependency>...</dependency>
<dependency>...</dependency>
...
</dependencies>
(2)Idea自动配置:
五、聚合
-
什么是聚合
父模块下有很多个子模块,可以将所有子模块的构建工作(执行各个生命周期)交给父模块统一处理。 -
配置方法
在父模块的pom.xml
文件中配置:<!--父模块的坐标信息--> ... <!--设置parent不打jar包--> <packaging>pom</packaging> <!--父模块的管理依赖信息--> ... <!--要聚合的所有子模块--> <modules> <!--要聚合的子模块,写相对路径,相对父模块的pom.xml文件--> <module>../child1</modules> <!--上一级目录的child1模块--> <moudle>./child2</moudle> <!--当前目录下的child2模块--> <!--其他模块--> <moudle>...</moudle> <moudle>...</moudle> <moudle>...</moudle> ... </modules>