第一節(jié) 實(shí)驗(yàn)一:根據(jù)坐標(biāo)創(chuàng)建 Maven 工程
-
1、Maven 核心概念:坐標(biāo)
- ①數(shù)學(xué)中的坐標(biāo)
- ②Maven中的坐標(biāo)
- ③坐標(biāo)和倉庫中 jar 包的存儲路徑之間的對應(yīng)關(guān)系
-
2、實(shí)驗(yàn)操作
- ①創(chuàng)建目錄作為后面操作的工作空間
- ②在工作空間目錄下打開命令行窗口
- ③使用命令生成Maven工程
- ④調(diào)整
- ⑤自動(dòng)生成的 pom.xml 解讀
-
3、Maven核心概念:POM
- ①含義
- ②模型化思想
- ③對應(yīng)的配置文件
-
4、Maven核心概念:約定的目錄結(jié)構(gòu)
- ①各個(gè)目錄的作用
- ②約定目錄結(jié)構(gòu)的意義
- ③約定大于配置
1、Maven 核心概念:坐標(biāo)
1. ① 數(shù)學(xué)中的坐標(biāo)

使用 x、y、z 三個(gè)『向量』作為空間的坐標(biāo)系,可以在『空間』中唯一的定位到一個(gè)『點(diǎn)』。
2. ② Maven中的坐標(biāo)
### 1. \[1\]向量說明
1. 使用三個(gè)『向量』在『Maven的倉庫』中唯一的定位到一個(gè)『jar』包。
1. groupId:公司或組織的 id
2. artifactId:一個(gè)項(xiàng)目或者是項(xiàng)目中的一個(gè)模塊的 id
3. version:版本號
### 2. \[2\]三個(gè)向量的取值方式
1. groupId:**公司或組織域名的倒序,通常也會(huì)加上項(xiàng)目名稱**
1. 例如:com.www.maven
2. artifactId:**模塊的名稱,將來作為 Maven 工程的工程名**
3. version:**模塊的版本號,根據(jù)自己的需要設(shè)定**
1. 例如:SNAPSHOT 表示快照版本,正在迭代過程中,不穩(wěn)定的版本
2. 例如:RELEASE 表示正式版本【快照】
舉例:
* groupId:com.www.maven
* artifactId:pro01-www-maven
* version:1.0-SNAPSHOT
3. ③ 坐標(biāo)和倉庫中 jar 包的存儲路徑之間的對應(yīng)關(guān)系
### 1. 坐標(biāo):
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
上面坐標(biāo)對應(yīng)的 jar 包在 Maven 本地倉庫中的位置:
Maven本地倉庫根目錄\javax\servlet\servlet-api\2.5\servlet-api-2.5.jar
一定要學(xué)會(huì)根據(jù)坐標(biāo)到本地倉庫中找到對應(yīng)的 jar 包。
2、實(shí)驗(yàn)操作
①創(chuàng)建目錄作為后面操作的工作空間
例如:D:\Soft\JetBrains\DevInstall\apache-maven-3.8.6\maven-workspace\spaceVideo
WARNING
此時(shí)我們已經(jīng)有了三個(gè)目錄,分別是:
Maven 核心程序:中軍大帳
Maven 本地倉庫:兵營
本地工作空間:戰(zhàn)場
②在工作空間目錄下打開命令行窗口

③使用命令生成Maven工程

運(yùn)行** mvn archetype:generate** 命令
TIP
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 7:【直接回車,使用默認(rèn)值】
Define value for property 'groupId': com.www.maven
Define value for property 'artifactId': pro01-maven-java
Define value for property 'version' 1.0-SNAPSHOT: :【直接回車,使用默認(rèn)值】
Define value for property 'package' com.www.maven: :【直接回車,使用默認(rèn)值】
Confirm properties configuration: groupId: com.atguigu.maven artifactId: pro01-maven-java version: 1.0-SNAPSHOT package: com.www.maven Y: :【直接回車,表示確認(rèn)。如果前面有輸入錯(cuò)誤,想要重新輸入,則輸入 N 再回車?!?/p>
④調(diào)整
Maven 默認(rèn)生成的工程,對 junit 依賴的是較低的 3.8.1 版本,我們可以改成較適合的 4.12 版本。
自動(dòng)生成的 App.java 和 AppTest.java 可以刪除
<!-- 依賴信息配置 -->
<!-- dependencies復(fù)數(shù)標(biāo)簽:里面包含dependency單數(shù)標(biāo)簽 -->
<dependencies>
<!-- dependency單數(shù)標(biāo)簽:配置一個(gè)具體的依賴 -->
<dependency>
<!-- 通過坐標(biāo)來依賴其他jar包 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!-- 依賴的范圍 -->
<scope>test</scope>
</dependency>
</dependencies>
⑤自動(dòng)生成的 pom.xml 解讀
<!-- project 標(biāo)簽 :根標(biāo)簽 ,表示對當(dāng)前工程進(jìn)行配置、管理-->
<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 標(biāo)簽 : 從 Maven 2 開始 就固定是 4.0.0-->
<!-- 代表當(dāng)前 pom.xml 所采用的標(biāo)簽結(jié)構(gòu)-->
<modelVersion>4.0.0</modelVersion>
<!-- 坐標(biāo)信息 -->
<!-- groupId 標(biāo)簽 : 坐標(biāo)向量之一 : 代表公司或組織 開發(fā)的某一個(gè)項(xiàng)目 -->
<groupId>com.www.maven</groupId>
<!-- artifactId 標(biāo)簽: 坐標(biāo)向量之一 : 代表項(xiàng)目下的某一個(gè) 模塊 -->
<artifactId>pro01-maven-java</artifactId>
<!-- version 標(biāo)簽 : 坐標(biāo)向量之一 : 代表當(dāng)前模塊的版本 -->
<version>1.0-SNAPSHOT</version>
<!-- package 標(biāo)簽 : 打包方式 -->
<!-- 取值 jar :生成 jar 包,說明是一個(gè)普通的 Java 工程 -->
<!-- 取值 war : 生成 war 包 ,說明這是一個(gè) Web 工程 -->
<!-- 取值 pom :說明這個(gè)工程是用來管理其他工程的工程 -->
<packaging>jar</packaging>
<!-- 工程名 -->
<name>pro01-maven-java</name>
<!-- Maven 官網(wǎng)地址 -->
<url>http://maven.apache.org</url>
<!-- 在Maven 中定義屬性值 -->
<properties>
<!-- 在構(gòu)建過程中讀取 源碼時(shí)使用的字符集 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- dependence 標(biāo)簽: 配置具體依賴信息, 可以包含多個(gè) dependency 子標(biāo)簽 -->
<dependencies>
<!-- dependency 標(biāo)簽 :配置一個(gè)具體的依賴信息 -->
<dependency>
<!-- 坐標(biāo)信息 : 需要導(dǎo)入哪個(gè) jar 包 ,就配置他的坐標(biāo)信息即可 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!-- scope 標(biāo)簽 : 配置當(dāng)前依賴的范圍 -->
<scope>test</scope>
</dependency>
</dependencies>
</project>
3、Maven核心概念:POM
①含義
POM:Project Object Model,項(xiàng)目對象模型。和 POM 類似的是:DOM(Document Object Model),文檔對象模型。它們都是模型化思想的具體體現(xiàn)。
②模型化思想
POM 表示將工程抽象為一個(gè)模型,再用程序中的對象來描述這個(gè)模型。這樣我們就可以用程序來管理項(xiàng)目了。我們在開發(fā)過程中,最基本的做法就是將現(xiàn)實(shí)生活中的事物抽象為模型,然后封裝模型相關(guān)的數(shù)據(jù)作為一個(gè)對象,這樣就可以在程序中計(jì)算與現(xiàn)實(shí)事物相關(guān)的數(shù)據(jù)。
③對應(yīng)的配置文件
POM 理念集中體現(xiàn)在 Maven 工程根目錄下 pom.xml 這個(gè)配置文件中。所以這個(gè) pom.xml 配置文件就是 Maven 工程的核心配置文件。其實(shí)學(xué)習(xí) Maven 就是學(xué)這個(gè)文件怎么配置,各個(gè)配置有什么用。
4、Maven核心概念:約定的目錄結(jié)構(gòu)
①各個(gè)目錄的作用

另外還有一個(gè) target 目錄專門存放構(gòu)建操作輸出的結(jié)果。
②約定目錄結(jié)構(gòu)的意義
Maven 為了讓構(gòu)建過程能夠盡可能自動(dòng)化完成,所以必須約定目錄結(jié)構(gòu)的作用。
例如:Maven 執(zhí)行編譯操作,必須先去 Java 源程序目錄讀取 Java 源代碼,然后執(zhí)行編譯,最后把編譯結(jié)果存放在 target 目錄。
③約定大于配置
Maven 對于目錄結(jié)構(gòu)這個(gè)問題,沒有采用配置的方式,而是基于約定。這樣會(huì)讓我們在開發(fā)過程中非常方便。如果每次創(chuàng)建 Maven 工程后,還需要針對各個(gè)目錄的位置進(jìn)行詳細(xì)的配置,那肯定非常麻煩。
目前開發(fā)領(lǐng)域的技術(shù)發(fā)展趨勢就是:約定大于配置,配置大于編碼。
第二節(jié) 實(shí)驗(yàn)二:在 Maven 工程中編寫代碼
1、主體程序

主體程序指的是被測試的程序,同時(shí)也是將來在項(xiàng)目中真正要使用的程序。
package com.www.maven;
/**
* <p>
*
*
* @author Www
* <p>
* 郵箱: 483223455@qq.com
* <p>
* 創(chuàng)建時(shí)間: 2022/8/17 15:38 星期三
* <p>
*/
public class Calculator {
public int sum(int i, int j){
return i + j;
}
}
2、測試程序

package com.www.maven;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class CalculatorTest{
@Test
public void testSum(){
// 1.創(chuàng)建Calculator對象
Calculator calculator = new Calculator();
// 2.調(diào)用Calculator對象的方法,獲取到程序運(yùn)行實(shí)際的結(jié)果
int actualResult = calculator.sum(5, 3);
// 3.聲明一個(gè)變量,表示程序運(yùn)行期待的結(jié)果
int expectedResult = 8;
// 4.使用斷言來判斷實(shí)際結(jié)果和期待結(jié)果是否一致
// 如果一致:測試通過,不會(huì)拋出異常
// 如果不一致:拋出異常,測試失敗
assertEquals(expectedResult, actualResult);
}
}
第三節(jié) 實(shí)驗(yàn)三:執(zhí)行 Maven 的構(gòu)建命令
- 1、要求
- 2、清理操作
- 3、編譯操作
- 4、測試操作
- 5、打包操作
- 6、安裝操作
實(shí)驗(yàn)三:執(zhí)行 Maven 的構(gòu)建命令
1、要求
運(yùn)行 Maven 中和構(gòu)建操作相關(guān)的命令時(shí),必須進(jìn)入到 pom.xml 所在的目錄。如果沒有在 pom.xml 所在的目錄運(yùn)行 Maven 的構(gòu)建命令,那么會(huì)看到下面的錯(cuò)誤信息:
The goal you specified requires a project to execute but there is no POM in this directory
TIP
mvn -v 命令和構(gòu)建操作無關(guān),只要正確配置了 PATH,在任何目錄下執(zhí)行都可以。而構(gòu)建相關(guān)的命令要在 pom.xml 所在目錄下運(yùn)行——操作哪個(gè)工程,就進(jìn)入這個(gè)工程的 pom.xml 目錄。
2、清理操作
mvn clean
效果:刪除 target 目錄
3、編譯操作
- 主程序編譯:mvn compile
- 測試程序編譯:mvn test-compile
- 主體程序編譯結(jié)果存放的目錄:target/classes
- 測試程序編譯結(jié)果存放的目錄:target/test-classes
4、測試操作
mvn test
測試的報(bào)告存放的目錄:target/surefire-reports
5、打包操作
mvn package
打包的結(jié)果——jar 包,存放的目錄:target
6、安裝操作
mvn install
[INFO] Installing D:\maven-workspace\space201026\pro01-maven-java\target\pro01-maven-java-1.0-SNAPSHOT.jar to D:\maven-rep1026\com\atguigu\maven\pro01-maven-java\1.0-SNAPSHOT\pro01-maven-java-1.0-SNAPSHOT.jar
[INFO] Installing D:\maven-workspace\space201026\pro01-maven-java\pom.xml to D:\maven-rep1026\com\atguigu\maven\pro01-maven-java\1.0-SNAPSHOT\pro01-maven-java-1.0-SNAPSHOT.pom
安裝的效果是將本地構(gòu)建過程中生成的 jar 包存入 Maven 本地倉庫。這個(gè) jar 包在 Maven 倉庫中的路徑是根據(jù)它的坐標(biāo)生成的。
坐標(biāo)信息如下:
<!-- 坐標(biāo)信息 -->
<!-- 在本地倉庫中安裝后對應(yīng)的路徑 :com\www\maven\pro01-maven-java\1.0-SNAPSHOT\pro01-maven-java-1.0-SNAPSHOT.jar-->
<!-- groupId 標(biāo)簽 : 坐標(biāo)向量之一 : 代表公司或組織 開發(fā)的某一個(gè)項(xiàng)目 -->
<groupId>com.www.maven</groupId>
<!-- artifactId 標(biāo)簽: 坐標(biāo)向量之一 : 代表項(xiàng)目下的某一個(gè) 模塊 -->
<artifactId>pro01-maven-java</artifactId>
<!-- version 標(biāo)簽 : 坐標(biāo)向量之一 : 代表當(dāng)前模塊的版本 -->
<version>1.0-SNAPSHOT</version>
在 Maven 倉庫中生成的路徑如下:
D:\Soft\JetBrains\DevInstall\apache-maven-3.8.6\repository\com\www\maven\pro01-maven-java\1.0-SNAPSHOT\pro01-maven-java-1.0-SNAPSHOT.jar
另外,安裝操作還會(huì)將 pom.xml 文件轉(zhuǎn)換為 XXX.pom 文件一起存入本地倉庫。所以我們在 Maven 的本地倉庫中想看一個(gè) jar 包原始的 pom.xml 文件時(shí),查看對應(yīng) XXX.pom 文件即可,它們是名字發(fā)生了改變,本質(zhì)上是同一個(gè)文件。
第四節(jié) 實(shí)驗(yàn)四:創(chuàng)建 Maven 版的 Web 工程
- 1、說明
- 2、操作
- 3、生成的pom.xml
- 4、生成的Web工程的目錄結(jié)構(gòu)
-
5、創(chuàng)建 Servlet
- ①在 main 目錄下創(chuàng)建 java 目錄
- ②在 java 目錄下創(chuàng)建 Servlet 類所在的包的目錄
- ③在包下創(chuàng)建 Servlet 類
- ④在 web.xml 中注冊 Servlet
- 6、在 index.jsp 頁面編寫超鏈接
- 7、編譯
- 8、配置對 servlet-api.jar 包的依賴
- 9、將 Web 工程打包為 war 包
- 10、將 war 包部署到 Tomcat 上運(yùn)行
實(shí)驗(yàn)四:創(chuàng)建 Maven 版的 Web 工程
1、說明
使用 **mvn archetype:generate **命令生成 Web 工程時(shí),需要使用一個(gè)專門的 archetype。這個(gè)專門生成 Web 工程骨架的 archetype 可以參照官網(wǎng)看到它的用法:

參數(shù) archetypeGroupId、archetypeArtifactId、archetypeVersion 用來指定現(xiàn)在使用的 maven-archetype-webapp 的坐標(biāo)
2、操作
注意:如果在上一個(gè)工程的目錄下執(zhí)行 mvn archetype:generate 命令,那么 Maven 會(huì)報(bào)錯(cuò):不能在一個(gè)非 pom 的工程下再創(chuàng)建其他工程。所以不要再剛才創(chuàng)建的工程里再創(chuàng)建新的工程,請回到工作空間根目錄來操作。
然后運(yùn)行生成工程的命令:
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DarchetypeVersion=1.4
下面的操作按照提示執(zhí)行:
TIP
Define value for property 'groupId': com.www.maven Define value for property 'artifactId': pro02-maven-web Define value for property 'version' 1.0-SNAPSHOT: :【直接回車,使用默認(rèn)值】
Define value for property 'package' com.www.maven: :【直接回車,使用默認(rèn)值】
Confirm properties configuration: groupId: com.www.maven artifactId: pro02-maven-web version: 1.0-SNAPSHOT package: com.www.maven Y: :【直接回車,表示確認(rèn)】
3、生成的pom.xml
確認(rèn)打包的方式是war包形式
<packaging>war</packaging>
4、生成的Web工程的目錄結(jié)構(gòu)

webapp 目錄下有 index.jsp
WEB-INF 目錄下有 web.xml
5、創(chuàng)建 Servlet
①在 main 目錄下創(chuàng)建 java 目錄

②在 java 目錄下創(chuàng)建 Servlet 類所在的包的目錄

③在包下創(chuàng)建 Servlet 類
package com.www.maven;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
/**
* @author Www
*/
public class HelloServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("hello maven web");
}
}
④在 web.xml 中注冊 Servlet
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.www.maven.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
</web-app>
6、在 index.jsp 頁面編寫超鏈接
<html>
<body>
<h2>Hello World!</h2>
<a href="helloServlet">Access Servlet</a>
</body>
</html>
TIP
JSP全稱是 Java Server Page,和 Thymeleaf 一樣,是服務(wù)器端頁面渲染技術(shù)。這里我們不必關(guān)心 JSP 語法細(xì)節(jié),編寫一個(gè)超鏈接標(biāo)簽即可。
7、編譯
此時(shí)直接執(zhí)行 mvn compile 命令出錯(cuò):
DANGER
程序包 javax.servlet.http 不存在
程序包 javax.servlet 不存在
找不到符號
符號: 類 HttpServlet ....
上面的錯(cuò)誤信息說明:我們的 Web 工程用到了 HttpServlet 這個(gè)類,而 HttpServlet 這個(gè)類屬于 servlet-api.jar 這個(gè) jar 包。此時(shí)我們說,Web 工程需要依賴 servlet-api.jar 包。

8、配置對 servlet-api.jar 包的依賴
對于不知道詳細(xì)信息的依賴可以到 https://mvnrepository.com/ 網(wǎng)站查詢。使用關(guān)鍵詞搜索,然后在搜索結(jié)果列表中選擇適合的使用。

比如,我們找到的 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。重新執(zhí)行 mvn compile 命令。
9、將 Web 工程打包為 war 包
運(yùn)行 mvn package 命令,生成 war 包的位置如下圖所示:

10、將 war 包部署到 Tomcat 上運(yùn)行
將 war 包復(fù)制到 Tomcat/webapps 目錄下

啟動(dòng) Tomcat:


第五節(jié) 實(shí)驗(yàn)五:讓 Web 工程依賴 Java 工程
- 1、觀念
- 2、操作
-
3、在 Web 工程中,編寫測試代碼
- ①補(bǔ)充創(chuàng)建目錄
- ②確認(rèn) Web 工程依賴了 junit
- ③創(chuàng)建測試類
-
4、執(zhí)行Maven命令
- ①測試命令
- ②打包命令
- ③查看當(dāng)前 Web 工程所依賴的 jar 包的列表
- ④以樹形結(jié)構(gòu)查看當(dāng)前 Web 工程的依賴信息
1、觀念
明確一個(gè)意識:從來只有 Web 工程依賴 Java 工程,沒有反過來 Java 工程依賴 Web 工程。本質(zhì)上來說,Web 工程依賴的 Java 工程其實(shí)就是 Web 工程里導(dǎo)入的 jar 包。最終 Java 工程會(huì)變成 jar 包,放在 Web 工程的 ****WEB-INF/lib ****目錄下。
2、操作
在 pro02-maven-web 工程的 pom.xml 中,找到 dependencies 標(biāo)簽,在 dependencies 標(biāo)簽中做如下配置:
<dependency>
<!-- 配置對Java工程pro01-maven-java的依賴 -->
<!-- 具體的配置方式:在dependency標(biāo)簽內(nèi)使用坐標(biāo)實(shí)現(xiàn)依賴 -->
<groupId>com.www.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
3、在 Web 工程中,編寫測試代碼
①補(bǔ)充創(chuàng)建目錄
pro02-maven-web\src\test\java\com\www\maven
②確認(rèn) Web 工程依賴了 junit
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
③創(chuàng)建測試類
把 Java 工程的 CalculatorTest.java 類復(fù)制到 pro02-maven-wb\src\test\java\com\www\maven 目錄下
4、執(zhí)行Maven命令
①測試命令
mvn test
說明:測試操作中會(huì)提前自動(dòng)執(zhí)行編譯操作,測試成功就說明編譯也是成功的。
②打包命令
mvn package

通過查看 war 包內(nèi)的結(jié)構(gòu),我們看到被 Web 工程依賴的 Java 工程確實(shí)是會(huì)變成 Web 工程的 WEB-INF/lib 目錄下的 jar 包。

③查看當(dāng)前 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.www.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 格式顯示的是一個(gè) jar 包的坐標(biāo)信息。
格式是:
TIP
** groupId:artifactId:打包方式:version:依賴的范圍**
這樣的格式雖然和我們 XML 配置文件中坐標(biāo)的格式不同,但是本質(zhì)上還是坐標(biāo)信息,大家需要能夠認(rèn)識這樣的格式,將來從 Maven 命令的日志或錯(cuò)誤信息中看到這樣格式的信息,就能夠識別出來這是坐標(biāo)。進(jìn)而根據(jù)坐標(biāo)到Maven 倉庫找到對應(yīng)的jar包,用這樣的方式解決我們遇到的報(bào)錯(cuò)的情況。
④以樹形結(jié)構(gòu)查看當(dāng)前 Web 工程的依賴信息
mvn dependency:tree
TIP
[INFO] com.www.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.www.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
我們在 pom.xml 中并沒有依賴 hamcrest-core,但是它卻被加入了我們依賴的列表。原因是:junit 依賴了hamcrest-core,然后基于依賴的傳遞性,hamcrest-core 被傳遞到我們的工程了
第六節(jié) 實(shí)驗(yàn)六:測試依賴范圍
-
1、依賴范圍
- ①compile 和 test 對比
- ②compile 和 provided 對比
- ③結(jié)論
-
2、測試
- ①驗(yàn)證 compile 范圍對 main 目錄有效
- ②驗(yàn)證test范圍對main目錄無效
- ③驗(yàn)證test和provided范圍不參與服務(wù)器部署
- ④驗(yàn)證provided范圍對測試程序有效
1、依賴范圍
標(biāo)簽的位置:dependencies/dependency/scope
標(biāo)簽的可選值:compile/test/provided/system/runtime/import
①compile 和 test 對比
| main目錄(空間) | test目錄(空間) | 開發(fā)過程(時(shí)間) | 部署到服務(wù)器(時(shí)間) | |
|---|---|---|---|---|
| compile | 有效 | 有效 | 有效 | 有效 |
| test | 無效 | 有效 | 有效 | 無效 |
②compile 和 provided 對比
| main目錄(空間) | test目錄(空間) | 開發(fā)過程(時(shí)間) | 部署到服務(wù)器(時(shí)間) | |
|---|---|---|---|---|
| compile | 有效 | 有效 | 有效 | 有效 |
| provided | 有效 | 有效 | 有效 | 無效 |
③結(jié)論
compile:通常使用的第三方框架的 jar 包這樣在項(xiàng)目實(shí)際運(yùn)行時(shí)真正要用到的 jar 包都是以 compile 范圍進(jìn)行依賴的。比如 SSM 框架所需jar包。
test:測試過程中使用的 jar 包,以 test 范圍依賴進(jìn)來。比如 junit。
provided:在開發(fā)過程中需要用到的“服務(wù)器上的 jar 包”通常以 provided 范圍依賴進(jìn)來。比如 servlet-api、jsp-api。而這個(gè)范圍的 jar 包之所以不參與部署、不放進(jìn) war 包,就是避免和服務(wù)器上已有的同類 jar 包產(chǎn)生沖突,同時(shí)減輕服務(wù)器的負(fù)擔(dān)。說白了就是:“服務(wù)器上已經(jīng)有了,你就別帶啦!”
2、測試
①驗(yàn)證 compile 范圍對 main 目錄有效
TIP
main目錄下的類:HelloServlet 使用compile范圍導(dǎo)入的依賴:pro01-www-maven
驗(yàn)證:使用compile范圍導(dǎo)入的依賴對main目錄下的類來說是有效的
有效:HelloServlet 能夠使用 pro01-www-maven 工程中的 Calculator 類
驗(yàn)證方式:在 HelloServlet 類中導(dǎo)入 Calculator 類,然后編譯就說明有效。
②驗(yàn)證test范圍對main目錄無效
測試方式:在主體程序中導(dǎo)入org.junit.Test這個(gè)注解,然后執(zhí)行編譯。
具體操作:在pro01-maven-java\src\main\java\com\www\maven目錄下修改Calculator.java
package com.atguigu.maven;
import org.junit.Test;
public class Calculator {
public int sum(int i, int j){
return i + j;
}
}
執(zhí)行Maven編譯命令:
[ERROR] /D:/maven-workspace/space201026/pro01-maven-java/src/main/java/com/www/maven/Calculator.java:[3,17] 程序包org.junit不存在
③驗(yàn)證test和provided范圍不參與服務(wù)器部署
其實(shí)就是驗(yàn)證:通過compile范圍依賴的jar包會(huì)放入war包,通過test范圍依賴的jar包不會(huì)放入war包。
image.png
④驗(yàn)證provided范圍對測試程序有效
測試方式是在pro02-maven-web的測試程序中加入servlet-api.jar包中的類。
修改:pro02-maven-web\src\test\java\com\www\maven\CalculatorTest.java
package com.www.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.www.maven.Calculator;
// 靜態(tài)導(dǎo)入的效果是將Assert類中的靜態(tài)資源導(dǎo)入當(dāng)前類
// 這樣一來,在當(dāng)前類中就可以直接使用Assert類中的靜態(tài)資源,不需要寫類名
import static org.junit.Assert.*;
public class CalculatorTest{
@Test
public void testSum(){
// 1.創(chuàng)建Calculator對象
Calculator calculator = new Calculator();
// 2.調(diào)用Calculator對象的方法,獲取到程序運(yùn)行實(shí)際的結(jié)果
int actualResult = calculator.sum(5, 3);
// 3.聲明一個(gè)變量,表示程序運(yùn)行期待的結(jié)果
int expectedResult = 8;
// 4.使用斷言來判斷實(shí)際結(jié)果和期待結(jié)果是否一致
// 如果一致:測試通過,不會(huì)拋出異常
// 如果不一致:拋出異常,測試失敗
assertEquals(expectedResult, actualResult);
}
}
然后運(yùn)行Maven的編譯命令:mvn compile
然后看到編譯成功。
第七節(jié) 實(shí)驗(yàn)七:測試依賴的傳遞性
-
1、依賴的傳遞性
- ①概念
- ②傳遞的原則
- 2、使用 compile 范圍依賴 spring-core
- 3、驗(yàn)證 test 和 provided 范圍不能傳遞
1、依賴的傳遞性
①概念
A 依賴 B,B 依賴 C,那么在 A 沒有配置對 C 的依賴的情況下,A 里面能不能直接使用 C?
②傳遞的原則
在 A 依賴 B,B 依賴 C 的前提下,C 是否能夠傳遞到 A,取決于 B 依賴 C 時(shí)使用的依賴范圍。
* **B 依賴 C 時(shí)使用 compile 范圍:可以傳遞**
* **B 依賴 C 時(shí)使用 test 或 provided 范圍:不能傳遞,**所以需要這樣的 jar 包時(shí),就必須在需要的地方明確配置依賴才可以
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.www.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
還可以在 Web 工程中,使用 mvn dependency:tree 命令查看效果(需要重新將 pro01-maven-java 安裝到倉庫):
TIP
[INFO] com.www.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.www.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、驗(yàn)證 test 和 provided 范圍不能傳遞
從上面的例子已經(jīng)能夠看到,pro01-maven-java 依賴了 junit,但是在 pro02-maven-web 工程中查看依賴樹的時(shí)候并沒有看到 junit。
要驗(yàn)證 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>
效果還是和之前一樣:
TIP
[INFO] com.www.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.www.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
第八節(jié) 實(shí)驗(yàn)八:測試依賴的排除
- 1、概念
- 2、配置方式
- 3、測試
1、概念
當(dāng) A 依賴 B,B 依賴 C 而且 C 可以傳遞到 A 的時(shí)候,A 不想要 C,需要在 A 里面把 C 排除掉。而往往這種情況都是為了避免 jar 包之間的沖突。

所以配置依賴的排除其實(shí)就是阻止某些 jar 包的傳遞。因?yàn)檫@樣的 jar 包傳遞過來會(huì)和其他 jar 包沖突。
2、配置方式
<dependency>
<!-- 配置對 java 工程的依賴-->
<groupId>com.www.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
<!-- 配置 依賴的排除 -->
<exclusions>
<!-- 配置具體排除信息 ,讓 commons-logging 不要傳遞到當(dāng)前項(xiàng)目 -->
<exclusion>
<!-- 這里指定坐標(biāo)是不需要指定 version -->
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
3、測試
測試的方式:在 pro02-maven-web 工程中配置對 commons-logging 的排除
<dependency>
<!-- 配置對 java 工程的依賴-->
<groupId>com.www.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
<!-- 配置 依賴的排除 -->
<exclusions>
<!-- 配置具體排除信息 ,讓 commons-logging 不要傳遞到當(dāng)前項(xiàng)目 -->
<exclusion>
<!-- 這里指定坐標(biāo)是不需要指定 version -->
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
運(yùn)行 mvn dependency:tree 命令查看效果:
TIP
[INFO] com.www.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.www.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] \- org.springframework:spring-core:jar:4.0.0.RELEASE:compile
發(fā)現(xiàn)在 spring-core 下面就沒有 commons-logging 了。
第九節(jié) 實(shí)驗(yàn)九:繼承
- 1、概念
- 2、作用
- 3、舉例
-
4、操作
- ①創(chuàng)建父工程
- ②創(chuàng)建模塊工程
- ③查看被添加新內(nèi)容的父工程 pom.xml
- ④解讀子工程的pom.xml
- ⑤在父工程中配置依賴的統(tǒng)一管理
- ⑥子工程中引用那些被父工程管理的依賴
- ⑦在父工程中升級依賴信息的版本
- ⑧在父工程中聲明自定義屬性
- 5、實(shí)際意義
1、概念
Maven工程之間,A 工程繼承 B 工程
- B 工程:父工程
- A 工程:子工程
本質(zhì)上是 A 工程的 pom.xml 中的配置繼承了 B 工程中 pom.xml 的配置。
2、作用
在父工程中統(tǒng)一管理項(xiàng)目中的依賴信息,具體來說是管理依賴信息的版本。
它的背景是:
- 對一個(gè)比較大型的項(xiàng)目進(jìn)行了模塊拆分。
- 一個(gè) project 下面,創(chuàng)建了很多個(gè) module。
- 每一個(gè) module 都需要配置自己的依賴信息。
它背后的需求是:
- 在每一個(gè) module 中各自維護(hù)各自的依賴信息很容易發(fā)生出入,不易統(tǒng)一管理。
- 使用同一個(gè)框架內(nèi)的不同 jar 包,它們應(yīng)該是同一個(gè)版本,所以整個(gè)項(xiàng)目中使用的框架版本需要統(tǒng)一。
- 使用框架時(shí)所需要的 jar 包組合(或者說依賴信息組合)需要經(jīng)過長期摸索和反復(fù)調(diào)試,最終確定一個(gè)可用組合。這個(gè)耗費(fèi)很大精力總結(jié)出來的方案不應(yīng)該在新的項(xiàng)目中重新摸索。
通過在父工程中為整個(gè)項(xiàng)目維護(hù)依賴信息的組合既保證了整個(gè)項(xiàng)目使用規(guī)范、準(zhǔn)確的 jar 包;又能夠?qū)⒁酝慕?jīng)驗(yàn)沉淀下來,節(jié)約時(shí)間和精力。
3、舉例
在一個(gè)工程中依賴多個(gè) 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 時(shí)要求所有 Spring 自己的 jar 包版本必須一致。為了能夠?qū)@些 jar 包的版本進(jìn)行統(tǒng)一管理,我們使用繼承這個(gè)機(jī)制,將所有版本信息統(tǒng)一在父工程中進(jìn)行管理。
4、操作
①創(chuàng)建父工程
創(chuàng)建的過程和前面創(chuàng)建 pro01-maven-java 一樣。
工程名稱:pro03-maven-parent
工程創(chuàng)建好之后,要修改它的打包方式:
<groupId>com.www.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 當(dāng)前工程作為父工程,要去管理其他工程,打包方式必須是 pom -->
<packaging>pom</packaging>
只有打包方式為 pom 的 Maven 工程能夠管理其他 Maven 工程。打包方式為 pom 的 Maven 工程中不寫業(yè)務(wù)代碼,它是專門管理其他 Maven 工程的工程。
②創(chuàng)建模塊工程
模塊工程類似于 IDEA 中的 module,所以需要進(jìn)入 pro03-maven-parent 工程的根目錄,然后運(yùn)行 mvn archetype:generate 命令來創(chuàng)建模塊工程。
假設(shè),我們創(chuàng)建三個(gè)模塊工程:
image.png
③查看被添加新內(nèi)容的父工程 pom.xml
下面 modules 和 module 標(biāo)簽是聚合功能的配置
<!-- 聚合的配置 -->
<modules>
<module>pro04-maven-module</module>
<module>pro05-maven-modele</module>
<module>pro06-maven-module</module>
</modules>
④解讀子工程的pom.xml
<!-- parent 標(biāo)簽給當(dāng)前工程 配置父工程-->
<parent>
<!-- 通過指定 父工程的坐標(biāo)找到父工程 -->
<groupId>com.www.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<!-- 子工程的 groupId 如果和父工程一樣 ,則可以省略-->
<!-- <groupId>com.www.maven</groupId>-->
<!-- 省略 groupId 和 version 后 ,子工程自己的坐標(biāo)可以只保留 artifactId -->
<artifactId>pro04-maven-module</artifactId>
<!-- 子工程的 groupId 如果和父工程一樣 ,則可以省略-->
<!-- <version>1.0-SNAPSHOT</version>-->
⑤在父工程中配置依賴的統(tǒng)一管理
<!-- 使用dependencyManagement標(biāo)簽配置對依賴的管理 -->
<!-- 被管理的依賴并沒有真正被引入到工程 -->
<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>
⑥子工程中引用那些被父工程管理的依賴
關(guān)鍵點(diǎn):省略版本號
<!-- 子工程引用父工程中的依賴信息時(shí),可以把版本號去掉。 -->
<!-- 把版本號去掉就表示子工程中這個(gè)依賴的版本由父工程決定。 -->
<!-- 具體來說是由父工程的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>
⑦在父工程中升級依賴信息的版本
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
然后在子工程中運(yùn)行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
⑧在父工程中聲明自定義屬性
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 創(chuàng)建自己定義的屬性標(biāo)簽 -->
<!-- 標(biāo)簽名 : 屬性名-->
<!-- 標(biāo)簽值 : 屬性值-->
<!-- 引用方式:${www.spring.version}-->
<www.spring.version>5.2.14.RELEASE</www.spring.version>
</properties>
在需要的地方使用${}的形式來引用自定義的屬性名:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<!-- 通過引用屬性表達(dá)式設(shè)定版本號,這樣版本號就成了一個(gè)動(dòng)態(tài)值-->
<!-- 通過屬性名解析后才知道具體是什么值-->
<version>${www.spring.version}</version>
</dependency>
真正實(shí)現(xiàn)“一處修改,處處生效”。
5、實(shí)際意義

編寫一套符合要求、開發(fā)各種功能都能正常工作的依賴組合并不容易。如果公司里已經(jīng)有人總結(jié)了成熟的組合方案,那么再開發(fā)新項(xiàng)目時(shí),如果不使用原有的積累,而是重新摸索,會(huì)浪費(fèi)大量的時(shí)間。為了提高效率,我們可以使用工程繼承的機(jī)制,讓成熟的依賴組合方案能夠保留下來。
如上圖所示,公司級的父工程中管理的就是成熟的依賴組合方案,各個(gè)新項(xiàng)目、子系統(tǒng)各取所需即可。
第十節(jié) 實(shí)驗(yàn)十:聚合
- 1、聚合本身的含義
- 2、Maven 中的聚合
- 3、好處
- 4、聚合的配置
- 5、依賴循環(huán)問題
1、聚合本身的含義
部分組成整體
image.png
動(dòng)畫片《戰(zhàn)神金剛》中的經(jīng)典臺詞:“我來組成頭部!我來組成手臂!”就是聚合關(guān)系最生動(dòng)的體現(xiàn)。
2、Maven 中的聚合
使用一個(gè)“總工程”將各個(gè)“模塊工程”匯集起來,作為一個(gè)整體對應(yīng)完整的項(xiàng)目。
- 項(xiàng)目:整體
- 模塊:部分
TIP
概念的對應(yīng)關(guān)系:
從繼承關(guān)系角度來看:
父工程
子工程
從聚合關(guān)系角度來看:
總工程
模塊工程
3、好處
- 一鍵執(zhí)行 Maven 命令:很多構(gòu)建命令都可以在“總工程”中一鍵執(zhí)行。
以 mvn install 命令為例:Maven 要求有父工程時(shí)先安裝父工程;有依賴的工程時(shí),先安裝被依賴的工程。我們自己考慮這些規(guī)則會(huì)很麻煩。但是工程聚合之后,在總工程執(zhí)行 mvn install 可以一鍵完成安裝,而且會(huì)自動(dòng)按照正確的順序執(zhí)行。
- 配置聚合之后,各個(gè)模塊工程會(huì)在總工程中展示一個(gè)列表,讓項(xiàng)目中的各個(gè)模塊一目了然。
4、聚合的配置
在總工程中配置** modules **即可:
<modules>
<module>pro04-maven-module</module>
<module>pro05-maven-module</module>
<module>pro06-maven-module</module>
</modules>
5、依賴循環(huán)問題
如果 A 工程依賴 B 工程,B 工程依賴 C 工程,C 工程又反過來依賴 A 工程,那么在執(zhí)行構(gòu)建操作時(shí)會(huì)報(bào)下面的錯(cuò)誤:
DANGER
[ERROR] [ERROR] The projects in the reactor contain a cyclic reference:
這個(gè)錯(cuò)誤的含義是:循環(huán)引用。


