2022跟学尚硅谷Maven入门(一)纯命令行

news2024/11/14 23:52:17

2022跟学尚硅谷Maven入门 一 纯命令行

  • Maven从小白到专家
    • 应用场景
      • 开发过程
      • 自动部署
      • 私有仓库
    • 课程介绍
      • 小白目标
      • 普通开发人员目标
      • 资深开发人员目标
  • 第一章:Maven 概述
    • 第一节 为什么要学习Maven
      • Maven 作为依赖管理工具
        • (1)jar包的规模
        • (2)jar 包的来源
        • (3)jar包之间的依赖关系
      • Maven 作为构建管理工具
        • (1)你没有注意过的构建
        • (2)脱离 IDE 环境仍需构建
        • (3)结论
    • 第二节 什么是 Maven?
      • 1.构建
      • 2.依赖
      • 3.Maven 的工作机制
  • 第二章 Maven 核心程序解压和配置
    • 第一节 Maven 核心程序解压与配置
      • 1.Maven 官网地址
      • 2.解压Maven核心程序
      • 3.指定本地仓库
      • 4.配置阿里云提供的镜像仓库
        • (1).将原有的例子配置注释掉
        • (2)加入我们的配置
      • 5. 配置 Maven 工程的基础 JDK 版本
    • 第二节 配置环境变量
      • 1.检查 JAVAHOME 配置是否正确
      • 2.配置 MAVEN_HOME环境变量
      • 3.配置PATH
      • 4.验证
  • 第三章 使用 Maven:命令行环境
    • 第一节:实验一:根据坐标创建 Maven 工程
      • 1.Maven 核心概念:坐标
        • (1)数学中的坐标
        • (2)Maven中的坐标
        • (3)坐标和仓库中 jar 包的存储路径之间的对应关系
      • 2.实验操作
        • (1)创建目录作为后面操作的工作空间
        • (2)在工作空间目录下打开命令行窗口
        • (3)使用命令生成Maven工程
        • (4)调整
        • (5)自动生成的 pom.xml 解读
      • 3.Maven核心概念:POM
        • (1)含义
        • (2)模型化思想
        • (3) 对应的配置文件
      • 4.Maven核心概念:约定的目录结构
        • (1)各个目录的作用
        • (2)约定目录结构的意义
        • (3)约定大于配置
    • 第二节 实验二:在 Maven 工程中编写代码
      • 1.主体程序
      • 2.测试程序
    • 第三节 实验三:执行 Maven 的构建命令
      • 1.要求
      • 2.清理操作
      • 3.编译操作
      • 4.测试操作
      • 5.打包操作
      • 6.安装操作
    • 第四节 实验四:创建 Maven 版的 Web 工程
      • 1.说明
      • 2.操作
      • 3.生成的pom.xml
      • 4.生成的Web工程的目录结构
      • 5.创建 Servlet
        • (1)在 main 目录下创建 java 目录
        • (2)在 java 目录下创建 Servlet 类所在的包的目录
        • (3)在包下创建 Servlet 类
        • (4)在 web.xml 中注册 Servlet
      • 6.在 index.jsp 页面编写超链接
      • 7.编译
      • 8.配置对 servlet-api.jar 包的依赖
      • 9.将 Web 工程打包为 war 包
        • 10.将 war 包部署到 Tomcat 上运行
    • 第五节 实验五:让 Web 工程依赖 Java 工程
      • 1. 观念
      • 2.操作
      • 3.在 Web 工程中,编写测试代码
        • (1)补充创建目录
        • (2)确认 Web 工程依赖了 junit
        • (3)创建测试类
      • 4.执行Maven命令
        • (1)测试命令
        • (2)打包命令
        • (3)查看当前 Web 工程所依赖的 jar 包的列表
        • (4)以树形结构查看当前 Web 工程的依赖信息
    • 第六节 实验六:测试依赖范围
      • 1.依赖范围
        • (1)compile 和 test 对比
        • (2)compile 和 provided 对比
        • (3)结论
      • 2.测试
        • (1)验证 compile 范围对 main 目录有效
        • (2)验证compile对test有效
        • (3)验证compile在部署到服务器(时间)有效
        • (4)验证test范围对main目录无效
        • (5)验证test和provided范围不参与服务器部署
          • 验证test范围不参与服务器部署
          • 验证provided范围不参与服务器部署
        • (6)验证provided范围对测试程序有效
    • 第七节 实验七:测试依赖的传递性
      • 1.依赖的传递性
        • (1)概念
        • (2)传递的原则
      • 2.使用 compile 范围依赖 spring-core
      • 3.验证 test 和 provided 范围不能传递
    • 第八节 实验八:测试依赖的排除
      • 1.概念
      • 2.配置方式
      • 3.测试
    • 第九节 实验九:继承
      • 1.概念
      • 2.作用
      • 3.举例
      • 4.操作
        • (1)创建父工程
        • (2)创建模块工程
        • (3)查看被添加新内容的父工程 pom.xml
        • (4)解读子工程的pom.xml
        • (5)在父工程中配置依赖的统一管理
        • (6)子工程中引用那些被父工程管理的依赖
        • (7)在父工程中升级依赖信息的版本
        • (8)在父工程中声明自定义属性
      • 5.实际意义
    • 第十节 实验十:聚合
      • 1.聚合本身的含义
      • 2.Maven 中的聚合
      • 3.好处
      • 4.聚合的配置
      • 5.依赖循环问题

Maven从小白到专家

Maven从小白到专家

应用场景

开发过程

开发过程

自动部署

自动部署

私有仓库

私有仓库

课程介绍

课程介绍

小白目标

小白目标

普通开发人员目标

普通开发人员目标

资深开发人员目标

资深开发人员目标

第一章:Maven 概述

第一节 为什么要学习Maven

Maven 作为依赖管理工具

(1)jar包的规模

随着我们使用越来越多的框架,或者框架封装程度越来越高,项目中使用的jar包也越来越多。项目中,
一个模块里面用到上百个jar包是非常正常的。
比如下面的例子,我们只用到 SpringBoot、SpringCloud 框架中的三个功能:

Nacos 服务注册发现
Web 框架环境
图模板技术 Thymeleaf

最终却导入了 106 个 jar 包:
jar包
而如果使用 Maven 来引入这些 jar 包只需要配置三个『依赖』:

<!-- Nacos 服务注册发现启动器 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacosdiscovery</artifactId>
</dependency>
<!-- web启动器依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 视图模板技术 thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

(2)jar 包的来源

这个jar包所属技术的官网。官网通常是英文界面,网站的结构又不尽相同,甚至找到下载链接还发
现需要通过特殊的工具下载。
第三方网站提供下载。问题是不规范,在使用过程中会出现各种问题。

  1. jar包的名称
  2. jar包的版本
  3. jar包内的具体细节

而使用 Maven 后,依赖对应的 jar 包能够自动下载,方便、快捷又规范。

(3)jar包之间的依赖关系

框架中使用的 jar 包,不仅数量庞大,而且彼此之间存在错综复杂的依赖关系。依赖关系的复杂程度,
已经上升到了完全不能靠人力手动解决的程度。另外,jar 包之间有可能产生冲突。进一步增加了我们在
jar 包使用过程中的难度。
下面是前面例子中 jar 包之间的依赖关系:
jar 包之间的依赖关系

而实际上 jar 包之间的依赖关系是普遍存在的,如果要由程序员手动梳理无疑会增加极高的学习成本,
而这些工作又对实现业务功能毫无帮助。
而使用 Maven 则几乎不需要管理这些关系,极个别的地方调整一下即可,极大的减轻了我们的工作
量。

Maven 作为构建管理工具

(1)你没有注意过的构建

你可以不使用 Maven,但是构建必须要做。当我们使用 IDEA 进行开发时,构建是 IDEA 替我们做的。

(2)脱离 IDE 环境仍需构建

脱离 IDE 环境仍需构建

(3)结论

  1. 管理规模庞大的 jar 包,需要专门工具。
  2. 脱离 IDE 环境执行构建操作,需要专门工具。

第二节 什么是 Maven?

Maven 是 Apache 软件基金会组织维护的一款专门为 Java 项目提供构建和依赖管理支持的工具。

1.构建

Java 项目开发过程中,构建指的是使用『原材料生产产品』的过程。
(1)原材料

  1. Java 源代码
  2. 基于 HTML 的 Thymeleaf 文件
  3. 图片
  4. 配置文件
  5. ……

(2)产品

一个可以在服务器上运行的项目
构建过程包含的主要的环节:

  1. 清理:删除上一次构建的结果,为下一次构建做好准备
  2. 编译:Java 源程序编译成 *.class 字节码文件
  3. 测试:运行提前准备好的测试程序
  4. 报告:针对刚才测试的结果生成一个全面的信息
  5. 打包
    Java工程:jar包
    Web工程:war包
  6. 安装:把一个 Maven 工程经过打包操作生成的 jar 包或 war 包存入 Maven 仓库
  7. 部署
    部署 jar 包:把一个 jar 包部署到 Nexus 私服服务器上
    部署 war 包:借助相关 Maven 插件(例如 cargo),将 war 包部署到 Tomcat 服务器上

2.依赖

构建

3.Maven 的工作机制

Maven的工作机制

第二章 Maven 核心程序解压和配置

第一节 Maven 核心程序解压与配置

1.Maven 官网地址

首页:
Maven – Welcome to Apache Maven (opens new window)
下载页面:
Maven – Download Apache Maven (opens new window)
下载操作:
下载操作

2.解压Maven核心程序

核心程序压缩包:apache-maven-3.8.4-bin.zip,解压到非中文、没有空格的目录。例如:
解压包
在解压目录中,我们需要着重关注 Maven 的核心配置文件:conf/settings.xml

3.指定本地仓库

本地仓库默认值:用户家目录/.m2/repository。由于本地仓库的默认位置是在用户的家目录下,而家目
录往往是在 C 盘,也就是系统盘。将来 Maven 仓库中 jar 包越来越多,仓库体积越来越大,可能会拖慢
C 盘运行速度,影响系统性能。所以建议将 Maven 的本地仓库放在其他盘符下。配置方式如下:
配置本地仓库
配置本地仓库
本地目录
配置仓库

  <localRepository>/path/to/local/repo</localRepository>
  -->
    <!-- 配置Maven本地仓库 -->
    <localRepository>F:\MavenWareHouse</localRepository>

本地仓库这个目录,我们手动创建一个空的目录即可。
记住:一定要把 localRepository 标签从注释中拿出来。
注意:本地仓库本身也需要使用一个非中文、没有空格的目录。

4.配置阿里云提供的镜像仓库

Maven 下载 jar 包默认访问境外的中央仓库,而国外网站速度很慢。改成阿里云提供的镜像仓库,访问
国内网站,可以让 Maven 下载 jar 包的时候速度更快。配置的方式是:
注释掉

(1).将原有的例子配置注释掉

<!-- <mirror>
<id>maven-default-http-blocker</id>
<mirrorOf>external:http:*</mirrorOf>
<name>Pseudo repository to mirror external repositories initially using
HTTP.</name>
<url>http://0.0.0.0/</url>
<blocked>true</blocked>
</mirror> -->

(2)加入我们的配置

加入配置

<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

5. 配置 Maven 工程的基础 JDK 版本

如果按照默认配置运行,Java 工程使用的默认 JDK 版本是 1.5,而我们熟悉和常用的是 JDK 1.8 版本。
修改配置的方式是:将 profile 标签整个复制到 settings.xml 文件的 profiles 标签内。
注释
添加

<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>

第二节 配置环境变量

1.检查 JAVAHOME 配置是否正确

Maven 是一个用 Java 语言开发的程序,它必须基于 JDK 来运行,需要通过 JAVA_HOME 来找到 JDK 的
安装位置。
在这里插入图片描述

2.配置 MAVEN_HOME环境变量

配置MAVEN_HOME
在这里插入图片描述

3.配置PATH

环境变量Path

4.验证

验证
输入

mvn -v

可以看到上图的版本号

第三章 使用 Maven:命令行环境

第一节:实验一:根据坐标创建 Maven 工程

1.Maven 核心概念:坐标

(1)数学中的坐标

数学中的坐标

(2)Maven中的坐标

Maven中的坐标

(3)坐标和仓库中 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 包。

2.实验操作

(1)创建目录作为后面操作的工作空间

例如:D:\maven-workspace\space201026
WARNING
此时我们已经有了三个目录,分别是:
Maven 核心程序:中军大帐
Maven 本地仓库:兵营
本地工作空间:战场

(2)在工作空间目录下打开命令行窗口

在工作空间目录下打开命令行窗口

(3)使用命令生成Maven工程

使用命令生成Maven工程
运行 mvn archetype:generate 命令
下面根据提示操作
7快速开始
输入目录
artifactId输入

TIP
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 7:【直
接回车,使用默认值】
Define value for property ‘groupId’: com.atguigu.maven
Define value for property ‘artifactId’: pro01-maven-java
Define value for property ‘version’ 1.0-SNAPSHOT: :【直接回车,使用默认值】
Define value for property ‘package’ com.atguigu.maven: :【直接回车,使用默认值】
Confirm properties configuration: groupId: com.atguigu.maven artifactId: pro01-maven-java
version: 1.0-SNAPSHOT package: com.atguigu.maven Y: :【直接回车,表示确认。如果前面有
输入错误,想要重新输入,则输入 N 再回车。】

(4)调整

Maven 默认生成的工程,对 junit 依赖的是较低的 3.8.1 版本,我们可以改成较适合的 4.12 版本。
自动生成的 App.java 和 AppTest.java 可以删除。
更改版本号
删除类

<!-- 依赖信息配置 -->
<!-- dependencies复数标签:里面包含dependency单数标签 -->
<dependencies>
<!-- dependency单数标签:配置一个具体的依赖 -->
<dependency>
<!-- 通过坐标来依赖其他jar包 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!-- 依赖的范围 -->
<scope>test</scope>
</dependency>
</dependencies>

pom.xml初步解读

(5)自动生成的 pom.xml 解读

<!-- project标签:根标签:,表示对当前工程进行配置、管理 -->
<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 标签:从Maven2开始就固定是4.0.0  -->
  <!-- 代表当前pom.xml所采用的标签 -->
  <modelVersion>4.0.0</modelVersion>

<!-- gav坐标信息 -->
<!-- groupId标签:坐标之一,代表公司或者组织开发的某一个项目-->
  <groupId>com.atguigu.maven</groupId>
  <!-- artifactId标签:坐标向量之一,代表项目下的某一个模块  -->
  <artifactId>pro01-maven-java</artifactId>
  <!-- version标签:坐标向量之一,代表当前模块的版本  -->
  <version>1.0-SNAPSHOT</version>
  <!-- packaging标签:打包的方式 -->
  <!-- 取值:jar包,说明是一个Java工程,如果是war包,就是一个web工程,如果是pom,就是用来管理其它工程的工程-->
  <packaging>jar</packaging>

  <name>pro01-maven-java</name>
  <url>http://maven.apache.org</url>
  
<!-- properties标签:用来在Maven中定义属性值 -->
  <properties>
  <!-- 在构建过程中读取源码时的字符集 -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
<!-- dependencies标签: 配置具体的依赖信息,一个dependencies标签可以包含多个dependency标签 -->
  <dependencies>
  <!-- dependency标签:用来配置一个具体的依赖信息 -->
    <dependency>
	<!-- 坐标信息:想导入哪个jar包,就配置它的坐标信息即可 -->
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
	  <!-- scope标签:配置当前依赖的范围  -->
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>


3.Maven核心概念:POM

(1)含义

POM:Project Object Model,项目对象模型。和 POM 类似的是:DOM(Document Object
Model),文档对象模型。它们都是模型化思想的具体体现。

(2)模型化思想

POM 表示将工程抽象为一个模型,再用程序中的对象来描述这个模型。这样我们就可以用程序来管理项
目了。我们在开发过程中,最基本的做法就是将现实生活中的事物抽象为模型,然后封装模型相关的数
据作为一个对象,这样就可以在程序中计算与现实事物相关的数据。

(3) 对应的配置文件

POM 理念集中体现在 Maven 工程根目录下 pom.xml 这个配置文件中。所以这个 pom.xml 配置文件就
是 Maven 工程的核心配置文件。其实学习 Maven 就是学这个文件怎么配置,各个配置有什么用。

4.Maven核心概念:约定的目录结构

(1)各个目录的作用

各个目录的作用
超级POM是所有POM的父POM

(2)约定目录结构的意义

Maven 为了让构建过程能够尽可能自动化完成,所以必须约定目录结构的作用。例如:Maven 执行编译操作,必须先去 Java 源程序目录读取 Java 源代码,然后执行编译,最后把编译结果存放在 target 目录。

(3)约定大于配置

Maven 对于目录结构这个问题,没有采用配置的方式,而是基于约定。这样会让我们在开发过程中非常
方便。如果每次创建 Maven 工程后,还需要针对各个目录的位置进行详细的配置,那肯定非常麻烦。
目前开发领域的技术发展趋势就是:约定大于配置,配置大于编码。
编码 → 配置 → 约定

第二节 实验二:在 Maven 工程中编写代码

1.主体程序

主体程序
主体程序指的是被测试的程序,同时也是将来在项目中真正要使用的程序。

package com.atguigu.maven;
public class Calculator {
public int sum(int i, int j){
return i + j;
}
}

2.测试程序

测试程序

package com.atguigu.maven;
import org.junit.Test;
import com.atguigu.maven.Calculator;
// 静态导入的效果是将Assert类中的静态资源导入当前类
// 这样一来,在当前类中就可以直接使用Assert类中的静态资源,不需要写类名
import static org.junit.Assert.*;
public class CalculatorTest{
@Test
public void testSum(){
// 1.创建Calculator对象
Calculator calculator = new Calculator();
// 2.调用Calculator对象的方法,获取到程序运行实际的结果
int actualResult = calculator.sum(5, 3);
// 3.声明一个变量,表示程序运行期待的结果
int expectedResult = 8;
// 4.使用断言来判断实际结果和期待结果是否一致
// 如果一致:测试通过,不会抛出异常
// 如果不一致:抛出异常,测试失败
assertEquals(expectedResult, actualResult);
}
}

第三节 实验三:执行 Maven 的构建命令

1.要求

运行 Maven 中和构建操作相关的命令时,必须进入到 pom.xml 所在的目录。如果没有在 pom.xml 所
在的目录运行 Maven 的构建命令,那么会看到下面的错误信息:

The goal you specified requires a project to execute but there is no POM in this directory

TIP
mvn -v 命令和构建操作无关,只要正确配置了 PATH,在任何目录下执行都可以。而构建相关的
命令要在 pom.xml 所在目录下运行——操作哪个工程,就进入这个工程的 pom.xml 目录。

2.清理操作

清理命令

mvn clean
效果:删除 target 目录
清除目录

3.编译操作

主程序编译:mvn compile
mvn compile
编译结果

测试程序编译:mvn test-compile
编译测试类

主体程序编译结果存放的目录:target/classes
编译后的class类

测试程序编译结果存放的目录:target/test-classes
编译后测试类

4.测试操作

mvn test
测试操作
测试的报告存放的目录:target/surefire-reports
测试报告位置

5.打包操作

mvn package
打包

打包的结果——jar 包,存放的目录:target
打包

6.安装操作

仓库执行之前
安装前清理

mvn install

[INFO] Installing F:\MavenWorkSpace\pro01-maven-java\target\pro01-maven-java-1.0-SNAPSHOT.jar to F:\MavenWareHouse\com\atguigu\maven\pro01-maven-java\1.0-SNAPSHOT\pro01-maven-java-1.0-SNAPSHOT.jar
[INFO] Installing F:\MavenWorkSpace\pro01-maven-java\pom.xml to F:\MavenWareHouse\com\atguigu\maven\pro01-maven-java\1.0-SNAPSHOT\pro01-maven-java-1.0-SNAPSHOT.pom

安装的效果是将本地构建过程中生成的 jar 包存入 Maven 本地仓库。这个 jar 包在 Maven 仓库中的路
径是根据它的坐标生成的。
坐标信息如下:

<groupId>com.atguigu.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>

在 Maven 仓库中生成的路径如下:

F:\MavenWareHouse\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 版的 Web 工程

1.说明

使用 mvn archetype:generate 命令生成 Web 工程时,需要使用一个专门的 archetype。这个专门生成
Web 工程骨架的 archetype 可以参照官网看到它的用法:
官网用法
参数 archetypeGroupId、archetypeArtifactId、archetypeVersion 用来指定现在使用的 maven-archetype-webapp 的坐标。

2.操作

注意:如果在上一个工程的目录下执行 mvn archetype:generate 命令,那么 Maven 会报错:不能在一
个非 pom 的工程下再创建其他工程。所以不要再刚才创建的工程里再创建新的工程,请回到工作空间
根目录来操作。
然后运行生成工程的命令:

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -
DarchetypeArtifactId=maven-archetype-webapp -DarchetypeVersion=1.4

执行命令如下
输入groupId
输入groupId
输入artifactId
输入命令

下面的操作按照提示执行:

TIP
Define value for property ‘groupId’: com.atguigu.maven Define value for property ‘artifactId’:
pro02-maven-web Define value for property ‘version’ 1.0-SNAPSHOT: :【直接回车,使用默认
值】
Define value for property ‘package’ com.atguigu.maven: :【直接回车,使用默认值】 Confirm
properties configuration: groupId: com.atguigu.maven artifactId: pro02-maven-web version:
1.0-SNAPSHOT package: com.atguigu.maven Y: :【直接回车,表示确认】
创建成功

3.生成的pom.xml

确认打包的方式是war包形式

<packaging>war</packaging>

4.生成的Web工程的目录结构

生成的Web工程的目录结构
webapp 目录下有 index.jsp
WEB-INF 目录下有 web.xml

5.创建 Servlet

(1)在 main 目录下创建 java 目录

main中创建目录

(2)在 java 目录下创建 Servlet 类所在的包的目录

目录下创建目录

(3)在包下创建 Servlet 类

package com.atguigu.maven;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
public class HelloServlet extends HttpServlet{
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
response.getWriter().write("hello maven web");
}
}

创建类

(4)在 web.xml 中注册 Servlet

<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.atguigu.maven.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>

注册

6.在 index.jsp 页面编写超链接

<html>
<body>
<h2>Hello World!</h2>
<a href="helloServlet">Access Servlet</a>
</body>
</html>

编写jsp

TIP
JSP全称是 Java Server Page,和 Thymeleaf 一样,是服务器端页面渲染技术。这里我们不必关心
JSP 语法细节,编写一个超链接标签即可。

7.编译

此时直接执行 mvn compile 命令出错:

DANGER
程序包 javax.servlet.http 不存在
程序包 javax.servlet 不存在
找不到符号
符号: 类 HttpServlet
……
编译出错

上面的错误信息说明:我们的 Web 工程用到了 HttpServlet 这个类,而 HttpServlet 这个类属于
servlet-api.jar 这个 jar 包。此时我们说,Web 工程需要依赖 servlet-api.jar 包。
web工程

8.配置对 servlet-api.jar 包的依赖

对于不知道详细信息的依赖可以到https://mvnrepository.com/网站查询。使用关键词搜索,然后再搜索结果列表中选择适合的使用。
比如,我们找到的 servlet-api 的依赖信息:
依赖

<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

拷贝
这样就可以把上面的信息加入 pom.xml。重新执行 mvn compile 命令。
编译成功

9.将 Web 工程打包为 war 包

mvn clean package

运行 mvn package 命令,生成 war 包的位置如下图所示:
打包
war包

10.将 war 包部署到 Tomcat 上运行

将 war 包复制到 Tomcat/webapps 目录下:
war包复制
启动 Tomcat:
启动tomcat

通过浏览器尝试访问:http://localhost:8080/demo/index.jsp
尝试登录

第五节 实验五:让 Web 工程依赖 Java 工程

1. 观念

明确一个意识:从来只有 Web 工程依赖 Java 工程,没有反过来 Java 工程依赖 Web 工程。本质上来
说,Web 工程依赖的 Java 工程其实就是 Web 工程里导入的 jar 包。最终 Java 工程会变成 jar 包,放在
Web 工程的 WEB-INF/lib 目录下。

2.操作

在 pro02-maven-web 工程的 pom.xml 中,找到 dependencies 标签,在 dependencies 标签中做如
下配置:

<!-- 配置对Java工程pro01-maven-java的依赖 -->
<!-- 具体的配置方式:在dependency标签内使用坐标实现依赖 -->
<dependency>
<groupId>com.atguigu.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

配置依赖

3.在 Web 工程中,编写测试代码

(1)补充创建目录

pro02-maven-web\src\test\java\com\atguigu\maven
创建包

(2)确认 Web 工程依赖了 junit

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

配置依赖

(3)创建测试类

把 Java 工程的 CalculatorTest.java 类复制到 pro02-maven-wb\src\test\java\com\atguigu\maven
目录下
拷贝测试类

4.执行Maven命令

(1)测试命令

mvn test
说明:测试操作中会提前自动执行编译操作,测试成功就说明编译也是成功的。
测试命令

(2)打包命令

mvn clean package
打包指令

通过查看 war 包内的结构,我们看到被 Web 工程依赖的 Java 工程确实是会变成 Web 工程的 WEBINF/lib 目录下的 jar 包。
jar包

(3)查看当前 Web 工程所依赖的 jar 包的列表

mvn dependency:list
依赖列表

TIP
[INFO] The following files have been resolved:
[INFO] org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] javax.servlet:javax.servlet-api:jar:3.1.0:provided
[INFO] com.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] junit:junit:jar:4.12:test

说明:javax.servlet:javax.servlet-api:jar:3.1.0:provided 格式显示的是一个 jar 包的坐标信息。格式
是:

TIP
groupId:artifactId:打包方式:version:依赖的范围

这样的格式虽然和我们 XML 配置文件中坐标的格式不同,但是本质上还是坐标信息,大家需要能够认识
这样的格式,将来从 Maven 命令的日志或错误信息中看到这样格式的信息,就能够识别出来这是坐
标。进而根据坐标到Maven 仓库找到对应的jar包,用这样的方式解决我们遇到的报错的情况。

(4)以树形结构查看当前 Web 工程的依赖信息

mvn dependency:tree
树形结构

TIP
[INFO] com.atguigu.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.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile

我们在 pom.xml 中并没有依赖 hamcrest-core,但是它却被加入了我们依赖的列表。原因是:junit 依
赖了hamcrest-core,然后基于依赖的传递性,hamcrest-core 被传递到我们的工程了。

第六节 实验六:测试依赖范围

1.依赖范围

标签的位置:dependencies/dependency/scope
标签的可选值:compile/test/provided/system/runtime/import

(1)compile 和 test 对比

main目录(空间)test目录(空间)开发过程(时间)部署到服务器(时间)
compile有效有效有效有效
test无效有效有效无效

(2)compile 和 provided 对比

main目录(空间)test目录(空间)开发过程(时间)部署到服务器(时间)
compile有效有效有效有效
provided有效有效有效无效

(3)结论

compile:通常使用的第三方框架的 jar 包这样在项目实际运行时真正要用到的 jar 包都是以 compile 范
围进行依赖的。比如 SSM 框架所需jar包。
test:测试过程中使用的 jar 包,以 test 范围依赖进来。比如 junit。
provided:在开发过程中需要用到的“服务器上的 jar 包”通常以 provided 范围依赖进来。比如 servletapi、jsp-api。而这个范围的 jar 包之所以不参与部署、不放进 war 包,就是避免和服务器上已有的同类
jar 包产生冲突,同时减轻服务器的负担。说白了就是:“服务器上已经有了,你就别带啦!”

2.测试

验证范围

(1)验证 compile 范围对 main 目录有效

TIP
main目录下的类:HelloServlet 使用compile范围导入的依赖:pro01-atguigu-maven
验证:使用compile范围导入的依赖对main目录下的类来说是有效的
有效:HelloServlet 能够使用 pro01-atguigu-maven 工程中的 Calculator 类
验证方式:在 HelloServlet 类中导入 Calculator 类,然后编译就说明有效。

package com.atguigu.maven;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
// 通过 import 语句,将要测试的类引入当前类,引入后如果
// 编译成功:可以使用,这个范围的依赖对当前类有效
// 编译失败:不能使用,这个范围的依赖对当前类无效
import com.atguigu.maven.Calculator;

// main目录下的Java类,HelloServlet
// scope范围:compile 引入的依赖 pro01-maven-java
// pro01-maven-java中的类就是 Calculator
// 验证目标:HelloServlet 能否使用 Calculator
public class HelloServlet extends HttpServlet{
	protected void doGet(HttpServletRequest request, HttpServletResponseresponse) throws ServletException, IOException {
		response.getWriter().write("hello maven web");
	}
}

重新编译
编译成功

(2)验证compile对test有效

修改CalculatorTest类

package com.atguigu.maven;
import org.junit.Test;
import com.atguigu.maven.Calculator;
// 静态导入的效果是将Assert类中的静态资源导入当前类
// 这样一来,在当前类中就可以直接使用Assert类中的静态资源,不需要写类名
import static org.junit.Assert.*;

// 测试方式
// 通过 import 语句,将要测试的类引入当前类,引入后如果
// 编译成功:可以使用,这个范围的依赖对当前类有效
// 编译失败:不能使用,这个范围的依赖对当前类无效

// test目录下的Java类 CalculatorTest
// scope范围:compile 引入的依赖 pro01-maven-java
// pro01-maven-java中的类就是 Calculator

public class CalculatorTest{
@Test
public void testSum(){
	// 1.创建Calculator对象
	Calculator calculator = new Calculator();
	// 2.调用Calculator对象的方法,获取到程序运行实际的结果
	int actualResult = calculator.sum(5, 3);
	// 3.声明一个变量,表示程序运行期待的结果
	int expectedResult = 8;
	// 4.使用断言来判断实际结果和期待结果是否一致
	// 如果一致:测试通过,不会抛出异常
	// 如果不一致:抛出异常,测试失败
	assertEquals(expectedResult, actualResult);
	System.out.println("testSum()被调用了!");
	}
}

看编译结果
看编译结果
编译成功

(3)验证compile在部署到服务器(时间)有效

打包
打包
打包目录如下
打包目录
目录生成的jar包,显示了compile范围引入的依赖会部署
compile范围

(4)验证test范围对main目录无效

测试方式:在主体程序中导入org.junit.Test这个注解,然后执行编译。
具体操作:在pro02-maven-web\src\main\java\com\atguigu\maven目录下修改HelloServlet.java

package com.atguigu.maven;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
// 通过 import 语句,将要测试的类引入当前类,引入后如果
// 编译成功:可以使用,这个范围的依赖对当前类有效
// 编译失败:不能使用,这个范围的依赖对当前类无效
import com.atguigu.maven.Calculator;

// main目录下的Java类,HelloServlet
// scope范围:compile 引入的依赖 pro01-maven-java
// pro01-maven-java中的类就是 Calculator
// 验证目标:HelloServlet 能否使用 Calculator

// test范围引入的依赖:junit
// junit中可以使用的注解@Test
import org.junit.Test;

public class HelloServlet extends HttpServlet{
	protected void doGet(HttpServletRequest request, HttpServletResponse 
	response) throws ServletException, IOException {
		response.getWriter().write("hello maven web");
	}
}

执行Maven编译命令:

[ERROR] /D:/maven-workspace/space201026/pro01-mavenjava/src/main/java/com/atguigu/maven/Calculator.java:[3,17] 程序包org.junit不存
在

编译失败
构建失败

(5)验证test和provided范围不参与服务器部署

验证test范围不参与服务器部署

其实就是验证:通过compile范围依赖的jar包会放入war包,通过test范围依赖的jar包不会放入war包。
打包

验证
服务部署

验证provided范围不参与服务器部署

provided范围
provided范围是servlet的api,我们发现tomcat已经有相同的api了
Tomcat部署
Tomcat已经提供了,所以部署到服务器是无效的

(6)验证provided范围对测试程序有效

测试方式是在pro02-maven-web的测试程序中加入servlet-api.jar包中的类。
修改:pro02-maven-web\src\test\java\com\atguigu\maven\CalculatorTest.java

package com.atguigu.maven;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import org.junit.Test;
import com.atguigu.maven.Calculator;
// 静态导入的效果是将Assert类中的静态资源导入当前类
// 这样一来,在当前类中就可以直接使用Assert类中的静态资源,不需要写类名
import static org.junit.Assert.*;
public class CalculatorTest{
@Test
public void testSum(){
// 1.创建Calculator对象
Calculator calculator = new Calculator();
// 2.调用Calculator对象的方法,获取到程序运行实际的结果
int actualResult = calculator.sum(5, 3);
// 3.声明一个变量,表示程序运行期待的结果
int expectedResult = 8;
// 4.使用断言来判断实际结果和期待结果是否一致
// 如果一致:测试通过,不会抛出异常
// 如果不一致:抛出异常,测试失败
assertEquals(expectedResult, actualResult);
}
}

然后运行Maven的编译命令:mvn compile
然后看到编译成功。

第七节 实验七:测试依赖的传递性

1.依赖的传递性

(1)概念

A 依赖 B,B 依赖 C,那么在 A 没有配置对 C 的依赖的情况下,A 里面能不能直接使用 C?

(2)传递的原则

在 A 依赖 B,B 依赖 C 的前提下,C 是否能够传递到 A,取决于 B 依赖 C 时使用的依赖范围。
B 依赖 C 时使用 compile 范围:可以传递
B 依赖 C 时使用 test 或 provided 范围:不能传递,所以需要这样的 jar 包时,就必须在需要的地
方明确配置依赖才可以。

2.使用 compile 范围依赖 spring-core

测试方式:让 pro01-maven-java 工程依赖 spring-core
加入依赖

具体操作:编辑 pro01-maven-java 工程根目录下 pom.xml

<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>

使用 mvn dependency:tree 命令查看效果:
查看依赖

TIP
[INFO] com.atguigu.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

spring-core:jar依赖于commons-logging:jar
依赖关系1
依赖关系 2

还可以在 Web 工程中,使用 mvn dependency:tree 命令查看效果(需要重新将 pro01-maven-java 安
装到仓库):
依赖关系
发现web工程和java工程的依赖关系没有显示spring-core,这里需要重新安装一下
重新编译
重新编译后
最后再查看依赖
最后查看依赖

TIP
[INFO] com.atguigu.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.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] - org.springframework:spring-core:jar:4.0.0.RELEASE:compile
[INFO] - commons-logging:commons-logging:jar:1.1.1:compile

3.验证 test 和 provided 范围不能传递

从上面的例子已经能够看到,pro01-maven-java 依赖了 junit,但是在 pro02-maven-web 工程中查看依赖树的时候并没有看到 junit。
要验证 provided 范围不能传递,可以在 pro01-maven-java 工程中加入 servlet-api 的依赖。

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

Java项目加入依赖
重新安装
重新安装
没有test和provided范围的依赖
没有test和provided

效果还是和之前一样:

TIP
[INFO] com.atguigu.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.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] - org.springframework:spring-core:jar:4.0.0.RELEASE:compile
[INFO] - commons-logging:commons-logging:jar:1.1.1:compile

第八节 实验八:测试依赖的排除

1.概念

当 A 依赖 B,B 依赖 C 而且 C 可以传递到 A 的时候,A 不想要 C,需要在 A 里面把 C 排除掉。而往往这种情况都是为了避免 jar 包之间的冲突。

依赖的排除
所以配置依赖的排除其实就是阻止某些 jar 包的传递。因为这样的 jar 包传递过来会和其他 jar 包冲突。

2.配置方式

<dependency>
<groupId>com.atguigu.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
<!-- 使用excludes标签配置依赖的排除 -->
<exclusions>
<!-- 在exclude标签中配置一个具体的排除 -->
<exclusion>
<!-- 指定要排除的依赖的坐标(不需要写version) -->
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

依赖的排除

3.测试

测试的方式:在 pro02-maven-web 工程中配置对 commons-logging 的排除

<dependency>
<groupId>com.atguigu.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
<!-- 使用excludes标签配置依赖的排除 -->
<exclusions>
<!-- 在exclude标签中配置一个具体的排除 -->
<exclusion>
<!-- 指定要排除的依赖的坐标(不需要写version) -->
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

运行 mvn dependency:tree 命令查看效果:
查看效果
发现在 spring-core 下面就没有 commons-logging 了。

TIP
[INFO] com.atguigu.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.atguigu.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] - org.springframework:spring-core:jar:4.0.0.RELEASE:compile

然后再看一下没有配置排除的Java工程是否有commons-logging呢,
可以看到依然是有的
依然存在

第九节 实验九:继承

1.概念

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

2.作用

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

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 包的版本进行统一管
理,我们使用继承这个机制,将所有版本信息统一在父工程中进行管理。

4.操作

(1)创建父工程

创建的过程和前面创建 pro01-maven-java 一样。
创建父工程
创建父工程2

工程名称:pro03-maven-parent
工程创建好之后,要修改它的打包方式:
配置打包方式

<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 工程的工程。

(2)创建模块工程

模块工程类似于 IDEA 中的 module,所以需要进入 pro03-maven-parent 工程的根目录,然后运行
mvn archetype:generate 命令来创建模块工程。
模块工程

假设,我们创建三个模块工程:
三个模块工程

(3)查看被添加新内容的父工程 pom.xml

下面 modules 和 module 标签是聚合功能的配置

<modules>
<module>pro04-maven-module</module>
<module>pro05-maven-module</module>
<module>pro06-maven-module</module>
</modules>

父工程pom.xml

(4)解读子工程的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> -->

(5)在父工程中配置依赖的统一管理

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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.atguigu.maven</groupId>
  <artifactId>pro03-maven-parent</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!-- <packaging>jar</packaging> -->
  <!-- 当前工程作为父工程,它要去管理子工程,所以打包方式必须是 pom -->
  <packaging>pom</packaging>


  <name>pro03-maven-parent</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

<!-- 聚合的配置 -->
  <modules>  
	<module>pro04-maven-module</module>
    <module>pro05-maven-module</module>
    <module>pro06-maven-module</module>
  </modules>
</project>

<!-- 在父工程中统一管理依赖信息 -->
<!-- 即使在父工程配置了对依赖的管理,子工程依然要配置依赖 -->
<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>4.0.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>4.0.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.0.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-expression</artifactId>
			<version>4.0.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>4.0.0.RELEASE</version>
		</dependency>
	</dependencies>
</dependencyManagement>

(6)子工程中引用那些被父工程管理的依赖

关键点:省略版本号

<!-- 子工程引用父工程中的依赖信息时,可以把版本号去掉。 -->
<!-- 把版本号去掉就表示子工程中这个依赖的版本由父工程决定。 -->
<!-- 具体来说是由父工程的dependencyManagement来决定。 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
</dependencies>

针对pro04
依赖配置
针对pro05
pox.xml配置

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.atguigu.maven</groupId>
    <artifactId>pro03-maven-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <groupId>com.atguigu.maven</groupId>
  <artifactId>pro05-maven-module</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>pro05-maven-module</name>
  <url>http://maven.apache.org</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
	
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-beans</artifactId>
		<version>4.0.0.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>4.0.0.RELEASE</version>
</dependency>
  </dependencies>
</project>

篇日志pro05
看到有spring-beans和spring-context

针对pro06
pom.xml配置

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.atguigu.maven</groupId>
    <artifactId>pro03-maven-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <groupId>com.atguigu.maven</groupId>
  <artifactId>pro06-maven-module</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>pro06-maven-module</name>
  <url>http://maven.apache.org</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
	
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-expression</artifactId>
		<version>4.0.0.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-aop</artifactId>
		<version>4.0.0.RELEASE</version>
	</dependency>
  </dependencies>
</project>

pro06

看到有spring-expression和spring-aop

(7)在父工程中升级依赖信息的版本

父工程版本号

……
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.0.RELEASE</version>
</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

pro06
版本号变为父类的版本号
版本号变为父类
pro05
版本号与父类相同
pro05
pro04
版本号与父类相同
pro04

(8)在父工程中声明自定义属性

自定义属性

<!-- 通过自定义属性,统一指定Spring的版本 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 自定义标签,维护Spring版本数据 -->
<atguigu.spring.version>4.2.0.RELEASE</atguigu.spring.version>
</properties>

在需要的地方使用${}的形式来引用自定义的属性名:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${atguigu.spring.version}</version>
</dependency>

版本号修改为4.2.0发现更改了
版本号
子工程版本号修改
在这里插入图片描述

真正实现“一处修改,处处生效”。
子工程也可以写自定义标签,并不是只有父类可以写。

5.实际意义

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

第十节 实验十:聚合

1.聚合本身的含义

部分组成整体
整体

动画片《战神金刚》中的经典台词:“我来组成头部!我来组成手臂!”就是聚合关系最生动的体现。

2.Maven 中的聚合

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

TIP
概念的对应关系:
从继承关系角度来看:
父工程
子工程
从聚合关系角度来看:
总工程
模块工程

3.好处

一键执行 Maven 命令:很多构建命令都可以在“总工程”中一键执行。
配置pro04:
配置pro04

	<!-- 测试据合之后可以一键安装,让pro04依赖pro05 -->
	<dependency>
		 <groupId>com.atguigu.maven</groupId>
		<artifactId>pro05-maven-module</artifactId>
		<version>1.0-SNAPSHOT</version>
	</dependency>

配置pro05

	<!-- 测试据合之后可以一键安装,让pro05依赖pro06 -->
	<dependency>
		 <groupId>com.atguigu.maven</groupId>
		<artifactId>pro06-maven-module</artifactId>
		<version>1.0-SNAPSHOT</version>
	</dependency>

配置完毕后执行
配置依赖
注意不要配置成循环依赖

mvn clean install

以 mvn install 命令为例:Maven 要求有父工程时先安装父工程;有依赖的工程时,先安装被依赖的
工程。我们自己考虑这些规则会很麻烦。但是工程聚合之后,在总工程执行 mvn install 可以一键完
成安装,而且会自动按照正确的顺序执行。

配置聚合之后,各个模块工程会在总工程中展示一个列表,让项目中的各个模块一目了然。

4.聚合的配置

在总工程中配置 modules 即可:

<modules>
<module>pro04-maven-module</module>
<module>pro05-maven-module</module>
<module>pro06-maven-module</module>
</modules>

5.依赖循环问题

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

DANGER
[ERROR] [ERROR] The projects in the reactor contain a cyclic reference:

这个错误的含义是:循环引用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/131067.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

APSIM练习:播种作物练—高粱作物模拟

在本练习中&#xff0c;您将观察作物在一个季节内的生长情况。您将更多地了解如何使用 APSIM 对施肥率进行“假设”实验。这些技能不仅可以用来试验施肥率&#xff0c;还可以用来试验变量&#xff0c;例如&#xff1a; 种植时间。播种率。作物比较和不同的起始土壤水分条件。 …

C++之异常

文章目录一、C 语言传统的处理错误的方式二、C 异常概念三、异常的使用1.异常的抛出和捕获2.异常的重新抛出3.异常安全4.异常规范四、自定义异常体系五、C 标准库的异常体系六、异常的优缺点一、C 语言传统的处理错误的方式 传统的错误处理机制&#xff1a;   ① 终止程序&a…

JUC(十)-线程池-ThreadPoolExecutor分析

ThreadPoolExecutor 应用 & 源码解析 文章目录ThreadPoolExecutor 应用 & 源码解析一、线程池相关介绍1.1 为什么有了JDK提供的现有的创建线程池的方法(Executors类中的方法),然而还需要自定义线程池ThreadPoolExecutor 提供的七个核心参数大致了解JDK提供的几种拒绝策…

一辆适合长途出行的电动跑车 奥迪RS e-tron GT正式上市

作为奥迪品牌电动化发展的先锋力作&#xff0c;奥迪RS e-tron GT不止是前瞻科技的呈现&#xff0c;在e-tron纯电技术的加持下&#xff0c;更传递着RS的情怀&#xff0c;承载着人们对GT豪华休旅生活的向往。 2022年12月30日&#xff0c;伴随着Audi Channel第九期直播节目盛大开播…

MySQL存储引擎介绍以及InnoDB引擎结构理解

目录存储引擎概述各个存储引擎介绍InnoDBMySIAMMemeory其他引擎引擎有关的SQL语句InnoDB引擎逻辑存储结构架构内存部分磁盘部分后台线程InnoDB三大特性存储引擎概述 数据引擎是与数据真正存储的磁盘文件打交道的&#xff0c;它的上层&#xff08;服务层&#xff09;将处理好的…

我的Python学习笔记:私有变量

一、私有变量的定义 在Python中&#xff0c;有以下几种方式来定义变量&#xff1a; xx&#xff1a;公有变量_xx&#xff1a;单前置下划线&#xff0c;私有化属性或方法&#xff0c;类对象和子类可以访问&#xff0c;from somemodule import *禁止导入__xx&#xff1a;双前置下…

掌握Python中列表生成式的五个原因

1. 引言 在Python中我们往往使用列表生成式来代替for循环&#xff0c;本文通过引入实际例子&#xff0c;来阐述这背后的原因。 闲话少说&#xff0c;我们直接开始吧&#xff01; 2. 简洁性 列表生成式允许我们在一行代码中创建一个列表并对其元素执行相应的操作&#xff0…

(十五)大白话我们每一行的实际数据在磁盘上是如何存储的?

文章目录 1、前情回顾2、真实数据是如何存储的?3、隐藏字段4、初步的把磁盘上的数据和内存里的数据给关联起来1、前情回顾 之前我们已经给大家讲过了,一行数据在磁盘文件里存储的时候,包括如下几部分: 首先会包含自己的变长字段的长度列表然后是NULL值列表接着是数据头然后…

图的概念及存储结构

文章目录图的概念图(graph)有向图(directed graph)无向图(undirected graph)加权图(weighted graph)无向完全图(undirected complete graph)有向完全图(directed complete graph)子图(subgraph)稀疏图与稠密图度路径与回路连通图与连通分量强连通图与强连通分量生成树图的存储结…

STM32H750自制开发板调试经验

​本篇只是一个记录&#xff0c;没啥可看的。 STM32H750硬件相关 STM32H750可以通过USB-OTG下载程序&#xff0c;也可以使用SWD进行调试&#xff0c;所以设计板子得时候将PA13和PA12预留出来即可&#xff0c;后续也可以用作usb虚拟串口&#xff08;CDC&#xff09;功能或者模拟…

stm32f407VET6 系统学习 day08 利用adc 模数转换 监控光敏电阻。

1. ADC 的知识 1.基本概念 &#xff1a; Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件 。典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。 2.STM32F4x ADC特点 1. 可配…

git操作

删除暂存区文件&#xff1a; git rm --cached 完整文件名 git rm --cached xxx.txt这个删&#xff0c;只是把暂存区里的文件删了&#xff0c;工作区里面的没有删 把本地文件添加到暂存区 git add完整文件名 例如&#xff1a;git add xxx.txt git add xxx.txt此时xxx.txt已经…

Linux 权限理解和学习

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; Linux学习之旅 &#x1f38a;每篇一句&#xff1a; 图片来源 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 Don’t argue with the people of strong determination, because they may ch…

AtCoder Beginner Contest 283 Ex. Popcount Sum(类欧经典问题:数x在二进制表示下第k位的值)

题目 t(t<1e5)组样例&#xff0c;每组样例给定n,m,r(1<m<n<1e9,0<r<m) 求[1,n]这n个数中&#xff0c;所有满足i%mr的数i的二进制的1的个数之和 即&#xff1a;&#xff0c; 其中&#xff0c;__builtin_popcount(i)统计的是i的二进制表示中&#xff0c;1的…

Web APIs

文章目录一. Web API介绍1. Web APIs 和 JS 基础关联性1.1 JS 的组成1.2 JS 基础阶段以及 Web APIs 阶段2. API的概念[3.Web API的概念](https://developer.mozilla.org/zh-CN/docs/Web/API)4. API 和 Web API 总结二. DOM 介绍1. DOM 简介1.1 什么是 DOM1.2 DOM 树2. 获取元素…

Linux-6 三剑客命令

Linux-6 三剑客命令 awk&#xff08;取列&#xff09; 将系统的IP地址打印出来 [rootdestiny ~]# yum install net-tools -y #分析&#xff1a;#1.肯定是需要拿到IP地址&#xff0c;仅看某一个特定的网卡&#xff1b;ifconfig#2.先想办法过滤出数据的那一行&#xff1b; ###行#…

5)Django Admin管理工具,Form组件,Auth

目录 一 Django Admin管理工具 激活管理工具 使用管理工具 复杂模型 自定义表单 内联(Inline)显示 列表页的显示 二 django Form组件 局部钩子和全局钩子 三 Django 用户认证&#xff08;Auth&#xff09;组件 一 Django Admin管理工具 Django 提供了基于 web 的管理…

年终报告撰写小技巧,你学会了吗?

年年岁岁花相似&#xff0c;岁岁年年人不同。 临近年底&#xff0c;又到了一年一度的年终报告时段了。同事间见面最让人头疼的问候&#xff0c;莫过于&#xff0c;“你的年终报告写了吗&#xff1f;” 有的人东拼西凑、应付了事&#xff0c;汇报内容乏善可陈&#xff0c;领导…

美美的圣诞树画出来-CoCube

2022年圣诞节到来啦&#xff0c;很高兴这次我们又能一起度过~ CSDN诚邀各位技术er分享关于圣诞节的各种技术创意&#xff0c;展现你与众不同的精彩&#xff01;参与本次投稿即可获得【话题达人】勋章【圣诞快乐】定制勋章&#xff08;1年1次&#xff0c;错过要等下一年喔&#…

尚医通-上传医院接口实现(十八)

目录&#xff1a; &#xff08;1&#xff09;上传医院接口-基础类的创建 &#xff08;2&#xff09;数据接口-上传医院接口-初步实现 &#xff08;3&#xff09;上传医院接口-最终实现 &#xff08;1&#xff09;上传医院接口-基础类的创建 复制相关的工具类&#xff1a;这…