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統一進行聚合成完整的功能或項目。(聚合關系建立在繼承關系上)