Java開發學習(三十)—-Maven聚合和繼承解析
一、聚合
-
分模組開發後,需要將這四個項目都安裝到本地倉庫,目前我們只能通過項目Maven面板的
install
來安裝,並且需要安裝四個,如果我們的項目足夠多,那麼一個個安裝起來還是比較麻煩的 -
如果四個項目都已經安裝成功,當ssm_pojo發生變化後,我們就得將ssm_pojo重新安裝到maven倉庫,但是為了確保我們對ssm_pojo的修改不會影響到其他項目模組,我們需要對所有的模組進行重新編譯,那又需要將所有的模組再來一遍
項目少的話還好,但是如果項目多的話,一個個操作項目就容易出現漏掉或重複操作的問題,所以我們就想能不能抽取一個項目,把所有的項目管理起來,以後我們要想操作這些項目,只需要操作這一個項目,其他所有的項目都走一樣的流程,這個不就很省事省力。
這就用到了我們接下來的聚合,
-
所謂聚合:將多個模組組織成一個整體,同時進行項目構建的過程稱為聚合
-
聚合工程:通常是一個不具有業務功能的”空”工程(有且僅有一個pom文件)
-
作用:使用聚合工程可以將多個工程編組,通過對聚合工程進行構建,實現對所包含的模組進行同步構建
-
當工程中某個模組發生更新(變更)時,必須保障工程中與已更新模組關聯的模組同步更新,此時可以使用聚合工程來解決批量模組同步構建的問題。
-
關於聚合具體的實現步驟為:
步驟1:創建一個空的maven項目
步驟2:將項目的打包方式改為pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>maven_01_parent</artifactId>
<version>1.0-RELEASE</version>
<packaging>pom</packaging>
</project>
說明:項目的packaging打包方式,我們接觸到的有三種,分別是
-
jar:默認情況,說明該項目為java項目
-
war:說明該項目為web項目
-
pom:說明該項目為聚合或繼承(後面會講)項目
步驟3:pom.xml添加所要管理的項目
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>maven_01_parent</artifactId>
<version>1.0-RELEASE</version>
<packaging>pom</packaging>
<!--設置管理的模組名稱 例如存在如下模組-->
<modules>
<module>../maven_02_ssm</module>
<module>../maven_03_pojo</module>
<module>../maven_04_dao</module>
</modules>
</project>
步驟4:使用聚合統一管理項目
測試發現,當maven_01_parent
的compile
被點擊後,所有被其管理的項目都會被執行編譯操作。這就是聚合工程的作用。
說明:聚合工程管理的項目在進行運行的時候,會按照項目與項目之間的依賴關係來自動決定執行的順序 ,按照倒序進行構建,和modules裡面的配置的順序無關。。
二、繼承
我們已經完成了使用聚合工程去管理項目,聚合工程進行某一個構建操作,其他被其管理的項目也會執行相同的構建操作。那麼接下來,我們再來分析下,多模組開發存在的另外一個問題,重複配置
的問題,我們先來看張圖:
-
spring-webmvc
、spring-jdbc
在三個項目模組中都有出現,這樣就出現了重複的內容 -
spring-test
只在ssm_crm和ssm_goods中出現,而在ssm_order中沒有,這裡是部分重複的內容 -
我們使用的spring版本目前是
5.2.10.RELEASE
,假如後期要想升級spring版本,所有跟Spring相關jar包都得被修改,涉及到的項目越多,維護成本越高
面對上面的這些問題,我們就得用到接下來的繼承
-
所謂繼承:描述的是兩個工程間的關係,與java中的繼承相似,子工程可以繼承父工程中的配置資訊,常見於依賴關係的繼承。
-
作用:
-
簡化配置
-
減少版本衝突
-
接下來,我們到程式中去看看繼承該如何實現?
步驟1:創建一個空的Maven項目並將其打包方式設置為pom
因為這一步和前面maven創建聚合工程的方式是一摸一樣,所以我們可以單獨創建一個新的工程,也可以直接和聚合公用一個工程。實際開發中,聚合和繼承一般也都放在同一個項目中,但是這兩個的功能是不一樣的。
步驟2:在子項目中設置其父工程
分別在maven_02_ssm
,maven_03_pojo
,maven_04_dao
的pom.xml中添加其父項目為maven_01_parent
<!--配置當前工程繼承自parent工程-->
<parent>
<groupId>com.itheima</groupId>
<artifactId>maven_01_parent</artifactId>
<version>1.0-RELEASE</version>
<!--設置父項目pom.xml位置路徑-->
<relativePath>../maven_01_parent/pom.xml</relativePath>
</parent>
步驟3:優化子項目共有依賴導入問題
-
將子項目共同使用的jar包都抽取出來,維護在父項目的pom.xml中
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>maven_01_parent</artifactId>
<version>1.0-RELEASE</version>
<packaging>pom</packaging>
<!--設置管理的模組名稱-->
<modules>
<module>../maven_02_ssm</module>
<module>../maven_03_pojo</module>
<module>../maven_04_dao</module>
</modules>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
</project>
-
刪除子項目中已經被抽取到父項目的pom.xml中的jar包,如在
maven_02_ssm
的pom.xml中將已經出現在父項目的jar包刪除掉
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>maven_02_ssm</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!--配置當前工程繼承自parent工程-->
<parent>
<groupId>com.itheima</groupId>
<artifactId>maven_01_parent</artifactId>
<version>1.0-RELEASE</version>
<relativePath>../maven_01_parent/pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
刪除完後,你會發現父項目中有依賴對應的jar包,子項目雖然已經將重複的依賴刪除掉了,但是刷新的時候,子項目中所需要的jar包依然存在。
當項目的<parent>
標籤被移除掉,會發現多出來的jar包依賴也會隨之消失。
-
將
maven_04_dao
maven_01_parent
的父項目坐標
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>maven_04_dao</artifactId>
<version>1.0-SNAPSHOT</version>
<!--配置當前工程繼承自parent工程-->
<parent>
<groupId>com.itheima</groupId>
<artifactId>maven_01_parent</artifactId>
<version>1.0-RELEASE</version>
<relativePath>../maven_01_parent/pom.xml</relativePath>
</parent>
</project>
刷新並查看Maven的面板,會發現maven_04_dao同樣引入了父項目中的所有依賴。
這樣我們就可以解決剛才提到的第一個問題,將子項目中的公共jar包抽取到父工程中進行統一添加依賴,這樣做的可以簡化配置,並且當父工程中所依賴的jar包版本發生變化,所有子項目中對應的jar包版本也會跟著更新。
步驟4:優化子項目依賴版本問題
如果把所有用到的jar包都管理在父項目的pom.xml,看上去更簡單些,但是這樣就會導致有很多項目引入了過多自己不需要的jar包。如上面看到的這張圖:
如果把所有的依賴都放在了父工程中進行統一維護,例如ssm_crm,ssm_goods,ssm_order都繼承至ssm_parent,並且ssm_parent裡面包含了spring-webmvc、spring-jdbc、spring-test等依賴,那這樣就會導致ssm_order項目中多引入了spring-test
的jar包(但其實是不需要),如果這樣的jar包過多的話,對於ssm_order來說也是一種”負擔”。
那針對於這種部分項目有的jar包,我們該如何管理優化呢?
-
在父工程mavne_01_parent的pom.xml來定義依賴管理
<!--定義依賴管理-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
-
將maven_02_ssm的pom.xml中的junit依賴刪除掉,刷新Maven
刷新完會發現,在maven_02_ssm項目中的junit依賴並沒有出現,所以我們得到一個結論:<dependencyManagement>
標籤不真正引入jar包,而是配置可供子項目選擇的jar包依賴。子項目要想使用它所提供的這些jar包,需要自己添加依賴,並且不需要指定<version>
-
在maven_02_ssm的pom.xml添加junit的依賴
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
注意:這裡就不需要添加版本了,這樣做的好處就是當父工程dependencyManagement標籤中的版本發生變化後,子項目中的依賴版本也會跟著發生變化
maven_02_ssm這個項目中的junit版本就會跟隨著父項目中的標籤dependencyManagement中junit的版本發生變化而變化。不需要junit的項目就不需要添加對應的依賴即可。
總結來說,繼承可以幫助做兩件事
-
將所有項目公共的jar包依賴提取到父工程的pom.xml中,子項目就可以不用重複編寫,簡化開發
-
將所有項目的jar包配置到父工程的dependencyManagement標籤下,實現版本管理,方便維護
-
dependencyManagement標籤不真正引入jar包,只是管理jar包的版本
-
子項目在引入的時候,只需要指定groupId和artifactId,不需要加version
-
當dependencyManagement標籤中jar包版本發生變化,所有子項目中有用到該jar包的地方對應的版本會自動隨之更新
-
三、聚合與繼承的區別
3.1 聚合與繼承的區別
兩種之間的作用:
-
聚合用於快速構建項目,對項目進行管理
-
繼承用於快速配置和管理子項目中所使用jar包的版本
聚合和繼承的相同點:
-
聚合與繼承的pom.xml文件打包方式均為pom,可以將兩種關係製作到同一個pom文件中
-
聚合與繼承均屬於設計型模組,並無實際的模組內容
聚合和繼承的不同點:
-
聚合是在當前模組中配置關係,聚合可以感知到參與聚合的模組有哪些
-
繼承是在子模組中配置關係,父模組無法感知哪些子模組繼承了自己