【后端】Maven 体系(三)

Maven 体系

7. 实验七:测试依赖的传递性

7.1 依赖的传递性

7.1.1 概念
  • A 依赖 B,B 依赖 C,那么在 A 没有配置对 C 的依赖的情况下,A 里面能不能直接使用 C?
7.1.2 传递的原则
  • 在 A 依赖 B,B 依赖 C 的前提下,C 是否能够传递到 A,取决于 B 依赖 C 时使用的依赖范围。
  • B 依赖 C 时使用 compile 范围:可以传递
  • B 依赖 C 时使用 test 或 provided 范围:不能传递,所以需要这样的 jar 包时,就必须在需要的地方明确配置依赖才可以。

7.2 使用 compile 范围依赖 spring-core

  • 测试方式:让 pro01-maven-java 工程依赖 spring-core
  • 具体操作:编辑 pro01-maven-java 工程根目录下 pom.xml
<dependency>
	<groupId>org.springframeworkgroupId>
	<artifactId>spring-coreartifactId>
	<version>4.0.0.RELEASEversion>
dependency>
  • 使用 mvn dependency:tree 命令查看效果:
TIP
[INFO] com.alex.maven:pro01-maven-java:jar:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.12:test
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] \- org.springframework:spring-core:jar:4.0.0.RELEASE:compile
[INFO] \- commons-logging:commons-logging:jar:1.1.1:compile

8. 实验八:测试依赖的排除

8.1 概念

  • 当 A 依赖 B,B 依赖 C 而且 C 可以传递到 A 的时候,A 不想要 C,需要在 A 里面把 C 排除掉。而往往这种情况都是为了避免 jar 包之间的冲突。
    【后端】Maven 体系(三)_第1张图片
  • 所以配置依赖的排除其实就是阻止某些 jar 包的传递。因为这样的 jar 包传递过来会和其他 jar 包冲突。

8.2 配置方式

<dependency>
	<groupId>com.alex.mavengroupId>
	<artifactId>pro01-maven-javaartifactId>
	<version>1.0-SNAPSHOTversion>
	<scope>compilescope>
	
	<exclusions>
		
		<exclusion>
			
			<groupId>commons-logginggroupId>
			<artifactId>commons-loggingartifactId>
		exclusion>
	exclusions>
dependency>

8.3 测试

  • 测试的方式:在 pro02-maven-web 工程中配置对 commons-logging 的排除
  • 运行 mvn dependency:tree 命令查看效果:
TIP

[INFO] com.alex.maven:pro02-maven-web:war:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.12:test
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided
[INFO] \- com.alex.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] \- org.springframework:spring-core:jar:4.0.0.RELEASE:compile
  • 发现在 spring-core 下面就没有 commons-logging 了。

9. 实验九:继承

9.1 概念

  • Maven工程之间,A 工程继承 B 工程
    • B 工程:父工程
    • A 工程:子工程
  • 本质上是 A 工程的 pom.xml 中的配置继承了 B 工程中 pom.xml 的配置。

9.2 作用

  • 在父工程中统一管理项目中的依赖信息,具体来说是管理依赖信息的版本。
  • 它的背景是:
    • 对一个比较大型的项目进行了模块拆分。
    • 一个 project 下面,创建了很多个 module。
    • 每一个 module 都需要配置自己的依赖信息。
  • 它背后的需求是:
    • 在每一个 module 中各自维护各自的依赖信息很容易发生出入,不易统一管理。
    • 使用同一个框架内的不同 jar 包,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一。
    • 使用框架时所需要的 jar 包组合(或者说依赖信息组合)需要经过长期摸索和反复调试,最终确定一个可用组合。这个耗费很大精力总结出来的方案不应该在新的项目中重新摸索。
  • 通过在父工程中为整个项目维护依赖信息的组合既保证了整个项目使用规范、准确的 jar 包;又能够将以往的经验沉淀下来,节约时间和精力。

9.3 举例

  • 在一个工程中依赖多个 Spring 的 jar 包
TIP

[INFO] +- org.springframework:spring-core:jar:4.0.0.RELEASE:compile
[INFO] | \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] +- org.springframework:spring-beans:jar:4.0.0.RELEASE:compile
[INFO] +- org.springframework:spring-context:jar:4.0.0.RELEASE:compile
[INFO] +- org.springframework:spring-expression:jar:4.0.0.RELEASE:compile
[INFO] +- org.springframework:spring-aop:jar:4.0.0.RELEASE:compile
[INFO] | \- aopalliance:aopalliance:jar:1.0:compile
  • 使用 Spring 时要求所有 Spring 自己的 jar 包版本必须一致。为了能够对这些 jar 包的版本进行统一管理,我们使用继承这个机制,将所有版本信息统一在父工程中进行管理。

9.4 操作

9.4.1 创建父工程
  • 创建的过程和前面创建 pro01-maven-java 一样。
  • 工程名称:pro03-maven-parent
  • 工程创建好之后,要修改它的打包方式
<groupId>com.atguigu.mavengroupId>
<artifactId>pro03-maven-parentartifactId>
<version>1.0-SNAPSHOTversion>


<packaging>pompackaging>
  • 只有打包方式为 pom 的 Maven 工程能够管理其他 Maven 工程。打包方式为 pom 的 Maven 工程中不写业务代码,它是专门管理其他 Maven 工程的工程。
9.4.2 创建模块工程
  • 模块工程类似于 IDEA 中的 module,所以需要进入 pro03-maven-parent 工程的根目录,然后运行 mvn archetype:generate 命令来创建模块工程。
  • 假设,我们创建三个模块工程:
    【后端】Maven 体系(三)_第2张图片
9.4.3 查看被添加新内容的父工程 pom.xml
  • 下面 modules 和 module 标签是聚合功能的配置
<modules>  
	<module>pro04-maven-modulemodule>
	<module>pro05-maven-modulemodule>
	<module>pro06-maven-modulemodule>
modules>
9.4.4 解读子工程的pom.xml

<parent>
	
	<groupId>com.alex.mavengroupId>
	<artifactId>pro03-maven-parentartifactId>
	<version>1.0-SNAPSHOTversion>
parent>




<artifactId>pro04-maven-moduleartifactId>

9.4.5 在父工程中配置依赖的统一管理


<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframeworkgroupId>
			<artifactId>spring-coreartifactId>
			<version>4.0.0.RELEASEversion>
		dependency>
		<dependency>
			<groupId>org.springframeworkgroupId>
			<artifactId>spring-beansartifactId>
			<version>4.0.0.RELEASEversion>
		dependency>
		<dependency>
			<groupId>org.springframeworkgroupId>
			<artifactId>spring-contextartifactId>
			<version>4.0.0.RELEASEversion>
		dependency>
		<dependency>
			<groupId>org.springframeworkgroupId>
			<artifactId>spring-expressionartifactId>
			<version>4.0.0.RELEASEversion>
		dependency>
		<dependency>
			<groupId>org.springframeworkgroupId>
			<artifactId>spring-aopartifactId>
			<version>4.0.0.RELEASEversion>
		dependency>
	dependencies>
dependencyManagement>
9.4.6 子工程中引用那些被父工程管理的依赖
  • 关键点:省略版本号



<dependencies>
	<dependency>
		<groupId>org.springframeworkgroupId>
		<artifactId>spring-coreartifactId>
	dependency>
	<dependency>
		<groupId>org.springframeworkgroupId>
		<artifactId>spring-beansartifactId>
	dependency>
	<dependency>
		<groupId>org.springframeworkgroupId>
		<artifactId>spring-contextartifactId>
	dependency>
	<dependency>
		<groupId>org.springframeworkgroupId>
		<artifactId>spring-expressionartifactId>
	dependency>
	<dependency>
		<groupId>org.springframeworkgroupId>
		<artifactId>spring-aopartifactId>
	dependency>
dependencies>
9.4.7 在父工程中升级依赖信息的版本
……
			<dependency>
				<groupId>org.springframeworkgroupId>
				<artifactId>spring-beansartifactId>
				<version>4.1.4.RELEASEversion>
			dependency>
……
  • 然后在子工程中运行mvn dependency:list,效果如下:
TIP

[INFO] org.springframework:spring-aop:jar:4.1.4.RELEASE:compile
[INFO] org.springframework:spring-core:jar:4.1.4.RELEASE:compile
[INFO] org.springframework:spring-context:jar:4.1.4.RELEASE:compile
[INFO] org.springframework:spring-beans:jar:4.1.4.RELEASE:compile
[INFO] org.springframework:spring-expression:jar:4.1.4.RELEASE:compile
9.4.8 在父工程中声明自定义属性

<properties>
	<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
	
	
	<alex.spring.version>4.3.6.RELEASEalex.spring.version>
properties>
  • 在需要的地方使用${}的形式来引用自定义的属性名:
<dependency>
	<groupId>org.springframeworkgroupId>
	<artifactId>spring-coreartifactId>
	<version>${alex.spring.version}version>
dependency>
  • 真正实现“一处修改,处处生效”。

9.5 实际意义

【后端】Maven 体系(三)_第3张图片

  • 编写一套符合要求、开发各种功能都能正常工作的依赖组合并不容易。如果公司里已经有人总结了成熟的组合方案,那么再开发新项目时,如果不使用原有的积累,而是重新摸索,会浪费大量的时间。为了提高效率,我们可以使用工程继承的机制,让成熟的依赖组合方案能够保留下来。
  • 如上图所示,公司级的父工程中管理的就是成熟的依赖组合方案,各个新项目、子系统各取所需即可。

10. 实验十:聚合

10.1 聚合本身的含义

  • 部分组成整体

10.2 Maven 中的聚合

  • 使用一个“总工程”将各个“模块工程”汇集起来,作为一个整体对应完整的项目。
    • 项目:整体
    • 模块:部分
TIP

概念的对应关系:

从继承关系角度来看:

父工程
子工程

从聚合关系角度来看:

总工程
模块工程

10.3 好处

  • 一键执行 Maven 命令:很多构建命令都可以在“总工程”中一键执行。
  • 以 mvn install 命令为例:Maven 要求有父工程时先安装父工程;有依赖的工程时,先安装被依赖的工程。我们自己考虑这些规则会很麻烦。但是工程聚合之后,在总工程执行 mvn install 可以一键完成安装,而且会自动按照正确的顺序执行。
  • 配置聚合之后,各个模块工程会在总工程中展示一个列表,让项目中的各个模块一目了然。

10.4 聚合的配置

  • 在总工程中配置 modules 即可:
<modules>  
	<module>pro04-maven-modulemodule>
	<module>pro05-maven-modulemodule>
	<module>pro06-maven-modulemodule>
modules>

10.5 依赖循环问题

  • 如果 A 工程依赖 B 工程,B 工程依赖 C 工程,C 工程又反过来依赖 A 工程,那么在执行构建操作时会报下面的错误:
DANGER

[ERROR] [ERROR] The projects in the reactor contain a cyclic reference:
  • 这个错误的含义是:循环引用。

四、使用Maven:IDEA环境

1. 创建父工程

1.1 创建 Project

【后端】Maven 体系(三)_第4张图片
【后端】Maven 体系(三)_第5张图片
【后端】Maven 体系(三)_第6张图片

1.2 开启自动导入

  • 创建 Project 后,IDEA 会自动弹出下面提示,我们选择『Enable Auto-Import』,意思是启用自动导入。
    在这里插入图片描述
  • 这个自动导入一定要开启,因为 Project、Module 新创建或 pom.xml 每次修改时都应该让 IDEA 重新加载 Maven 信息。这对 Maven 目录结构认定、Java 源程序编译、依赖 jar 包的导入都有非常关键的影响。
  • 另外也可以通过 IDEA 的 Settings 设置来开启:
    【后端】Maven 体系(三)_第7张图片

2. 配置Maven信息

  • 每次创建 Project 后都需要设置 Maven 家目录位置,否则 IDEA 将使用内置的 Maven 核心程序(不稳定)并使用默认的本地仓库位置。这样一来,我们在命令行操作过程中已下载好的 jar 包就白下载了,默认的本地仓库通常在 C 盘,还影响系统运行。
  • 配置之后,IDEA 会根据我们在这里指定的 Maven 家目录自动识别到我们在 settings.xml 配置文件中指定的本地仓库。
    【后端】Maven 体系(三)_第8张图片

3. 创建Java模块工程

【后端】Maven 体系(三)_第9张图片
【后端】Maven 体系(三)_第10张图片

4. 创建Web模块工程

4.1 创建模块

  • 按照前面的同样操作创建模块,此时这个模块其实还是一个Java模块。

4.2 修改打包方式

  • Web 模块将来打包当然应该是 war 包。
<packaging>warpackaging>

4.3 Web 设定

  • 首先打开项目结构菜单:
    【后端】Maven 体系(三)_第11张图片
  • 然后到 Facets 下查看 IDEA 是否已经帮我们自动生成了 Web 设定。正常来说只要我们确实设置了打包方式为 war,那么 IDEA 2019 版就会自动生成 Web 设定。
    【后端】Maven 体系(三)_第12张图片

4.4 借助IDEA生成web.xml

【后端】Maven 体系(三)_第13张图片
【后端】Maven 体系(三)_第14张图片

4.5 设置 Web 资源的根目录

  • 结合 Maven 的目录结构,Web 资源的根目录需要设置为 src/main/webapp 目录。
    【后端】Maven 体系(三)_第15张图片
    【后端】Maven 体系(三)_第16张图片

5. 其他操作

5.1 在IDEA中执行Maven命令

5.1.1 直接执行

【后端】Maven 体系(三)_第17张图片

5.1.2 手动输入

【后端】Maven 体系(三)_第18张图片
【后端】Maven 体系(三)_第19张图片
【后端】Maven 体系(三)_第20张图片
【后端】Maven 体系(三)_第21张图片

  • 如果有需要,还可以给命令后面附加参数:

【后端】Maven 体系(三)_第22张图片

5.2 在IDEA中查看某个模块的依赖信息

【后端】Maven 体系(三)_第23张图片

5.3 工程导入

  • Maven工程除了自己创建的,还有很多情况是别人创建的。而为了参与开发或者是参考学习,我们都需要导入到 IDEA 中。下面我们分几种不同情况来说明:
5.3.1 来自版本控制系统
  • 目前我们通常使用的都是 Git(本地库) + 码云(远程库)的版本控制系统
5.3.2 来自工程目录
  • 直接使用 IDEA 打开工程目录即可。例子:

  • [1]工程压缩包
    假设别人发给我们一个 Maven 工程的 zip 压缩包:maven-rest-demo.zip。从码云或GitHub上也可以以 ZIP 压缩格式对项目代码打包下载。

  • [2]解压
    如果你的所有 IDEA 工程有一个专门的目录来存放,而不是散落各处,那么首先我们就把 ZIP 包解压到这个指定目录中。
    【后端】Maven 体系(三)_第24张图片

  • [3]打开
    只要我们确认在解压目录下可以直接看到 pom.xml,那就能证明这个解压目录就是我们的工程目录。那么接下来让 IDEA 打开这个目录就可以了。
    【后端】Maven 体系(三)_第25张图片
    【后端】Maven 体系(三)_第26张图片

  • [4]设置 Maven 核心程序位置
    打开一个新的 Maven 工程,和新创建一个 Maven 工程是一样的,此时 IDEA 的 settings 配置中关于 Maven 仍然是默认值:
    【后端】Maven 体系(三)_第27张图片
    所以我们还是需要像新建 Maven 工程那样,指定一下 Maven 核心程序位置:
    【后端】Maven 体系(三)_第28张图片

5.4 模块导入

5.4.1 情景重现
  • 在实际开发中,通常会忽略模块(也就是module)所在的项目(也就是project)仅仅导入某一个模块本身。这么做很可能是类似这样的情况:比如基于 Maven 学习 SSM 的时候,做练习需要导入老师发给我们的代码参考。
    【后端】Maven 体系(三)_第29张图片
5.4.2 导入 Java 类型模块
  • 找到老师发的工程目录
    【后端】Maven 体系(三)_第30张图片

  • 导入 Java 类型模块

    • 找到老师发的工程目录
      【后端】Maven 体系(三)_第31张图片

    • 复制我们想要导入的模块目录
      【后端】Maven 体系(三)_第32张图片

    • 粘贴到我们自己工程目录下

      • 这个工程(project)是我们事先在 IDEA 中创建好的。
        【后端】Maven 体系(三)_第33张图片
        【后端】Maven 体系(三)_第34张图片
  • 在 IDEA 中执行导入
    【后端】Maven 体系(三)_第35张图片
    【后端】Maven 体系(三)_第36张图片
    【后端】Maven 体系(三)_第37张图片
    【后端】Maven 体系(三)_第38张图片
    【后端】Maven 体系(三)_第39张图片

  • 修改 pom.xml

    • 刚刚导入的 module 的父工程坐标还是以前的,需要改成我们自己的 project。
      【后端】Maven 体系(三)_第40张图片
      【后端】Maven 体系(三)_第41张图片
  • 最终效果
    【后端】Maven 体系(三)_第42张图片

5.4.3 导入 Web 类型模块
  • 其它操作和上面演示的都一样,只是多一步:删除多余的、不正确的 web.xml 设置。如下图所示:
    【后端】Maven 体系(三)_第43张图片

你可能感兴趣的:(后端,maven)