Maven專案之間的關係
依賴關係
單純的專案A中需要專案B中的資源,將專案B打成Jar包被A依賴,此時專案A直接呼叫專案B中資源即可。
專案A和專案B此時形成最基本的依賴關係。
繼承關係
需要場景:
如果多個子專案中使用的是相同的依賴或外掛,此時我們可以把相同的配置抽取到一個父專案中,進行統一的管理,保持一致性。所以繼承關係此時顯得比較重要,在java中,繼承體現在程式碼功能上,而maven中的繼承則體現在pom.xml,跟功能程式碼沒有關係,當專案A繼承了專案B,則專案A擁有了專案B的pom.xml檔案中所有依賴。當然繼承中也不同的用法和不同的場景。
我們在同級目錄建立01_parent、02_child、03_child,一個父專案,兩個子專案
01_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>
<!-- 將其作為maven專案的父專案,統一管理子專案的公共依賴 -->
<groupId>org.example</groupId>
<artifactId>01_parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 父專案的專有打包方式,該種方式,本專案不會被打包成 jar 或 war ,專案裡 src 目錄下程式碼無效(可刪除), pom.xml 有效,只是作為其它專案的父專案使用. -->
<packaging>pom</packaging>
<properties>
<spring-version>5.2.9.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<!--配置webmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
02_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>
<parent>
<groupId>org.example</groupId>
<artifactId>01_parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<!-- <groupId>org.example</groupId> 如果子專案和父專案在同一級目錄,使用parent標籤表明了父專案座標後,子專案的groupId可以省去 -->
<artifactId>02_child</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
03_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>
<parent>
<groupId>org.example</groupId>
<artifactId>01_parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>03_child</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
然後我們看看maven專案之間的關係:
我們很明顯的看到,兩個子專案都成功的擁有了父專案的依賴。maven的基本繼承關係就弄完了。
但是實際開發中,我們可能有多個功能不同得子專案,父專案中的依賴並不是每一個子專案都必須全部需要的。這個時候如果子專案擁有了父專案全部依賴就有點說不過去了,甚至可能產生jar包衝突。
這裡我們可以使用
<dependencyManagement>
標籤來解決我們上述的問題,這個標籤的作用其實相當於一個對所依賴 jar 包進行版本管理的管理器.( dependencyManagement 裡只是宣告依賴,並不實現引入)
這樣一來,父專案就像超市,子專案就像客戶,父專案將部分不是基本的依賴放入其中,子專案需要就宣告即可,不需要的話父專案也不會強人所難。
01_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>
<!-- 將其作為maven專案的父專案,統一管理子專案的公共依賴 -->
<groupId>org.example</groupId>
<artifactId>01_parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 父專案的專有打包方式,該種方式,本專案不會被打包成 jar 或 war ,專案裡 src 目錄下程式碼無效(可刪除), pom.xml 有效,只是作為其它專案的父專案使用. -->
<packaging>pom</packaging>
<properties>
<spring-version>5.2.9.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<!--配置webmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--dependencyManagement 標籤中宣告的依賴,只是作為一個 jar 包統一管理的管理器,實際上該標籤中宣告的依賴不會被引入-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
在01_parent這個“超市”中新增了log4j和commons-logging的兩個依賴供子專案選擇。
此時02_child需要log4j這個依賴:
<?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>org.example</groupId>
<artifactId>01_parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<!-- <groupId>org.example</groupId> 如果子專案和父專案在同一級目錄,使用parent標籤表明了父專案座標後,子專案的groupId可以省去 -->
<artifactId>02_child</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
</dependencies>
</project>
03_child需要commons-logging這個依賴:
<?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>org.example</groupId>
<artifactId>01_parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>03_child</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
</dependencies>
</project>
看maven專案之間的依賴:
此時02_child沒有了commons-logging,03_child沒有了log4j,我們已經解決了這個問題。
如果子專案使用的依賴不是父專案的版本,需要在子專案的pom中標明依賴的版本,否則預設使用的是父專案管理的版本。
其實我們這個問題主要是學習<dependencyManagement>
這一標籤在父專案中的作用
打包
此時我們對02_child進行打包會報錯,具體原因是:
Non-resolvable parent POM for org.example:02_child:1.0-SNAPSHOT: Could not find artifact org.example:01_parent:pom:1.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13@
說子專案解析不了父專案的POM檔案,parent.relativePath錯誤。其實,我們在子類的parent標籤中還要加一個<relativePath>
標籤,來指明父專案中POM的相對物理路徑,這樣子專案打包的時候,maven才能工具標籤找到父專案的POM地址,不然也不知道子專案的引用從哪來。
專案報錯:
-
子專案打包出錯:Invalid packaging for parent POM com.cloud:DemoName:1.0-SNAPSHOT, must be “pom“ but is “jar“。
我們必須在父專案中pom指定打包格式為POM:
<packaging>pom</packaging>
-
Could not find artifact com.cloud:DemoName:pom:1.0-SNAPSHOT
子專案打包前必須先打包父專案
聚合關係
聚合本身沒有實質的內容,隨著程式的發展,專案也會越來越大,功能越來越多,開發人員往往會將其劃分模組進行開發,功能清晰,設計清晰。maven的聚合特性就是將多個模組聚合在一起構建。並且聚合是建立在繼承關係上,父專案的作用除了統一管理子專案的依賴,還做最後統一構建所有子模組,實現一次構建多個專案!
此處做個比喻,有一天我們被要求製作一個“強大”的機器,機器人靠著很多零件組裝,團隊有4個人,一個管理員,三個開發人員,管理員將其工具包分成三個區域性零件交給我們開發,我們每人一個不同的零件開發模組,並在管理員下進行開發。我們開發時,如果零件模組之間沒有互相依賴的關係可以並行開發,如果有單向依賴關係那就得看具體需求了。
當我們開發完成後統一交給管理員對我們的區域性零件進行組裝,最後的結果就是管理員(Maven)統一聚合專案下所有子模組成為最終專案成果。
程式碼就不演示了,我使用的是MVC分成4個模組(pojo,mapper,serivce,controller),單項依賴感覺不能講的很清楚,其實自己對聚合關係也只是一知半解,瞭解基本,還沒有進行實質的開發。體會不到聚合關係帶來的便利(才學疏淺),要了解詳情就要去看別的部落格了。
小結
本次是對Maven專案之間三大關係的介紹:
- 最基本的依賴關係:A依賴B
- 繼承關係:B和C的公共依賴、部分依賴被A統一管理
- 聚合關係:B、C功能模組開發完,被A統一進行聚合成完整的功能或專案。(聚合關係建立在繼承關係上)