Maven高級篇
- 二 小黑子的Maven高級篇學習
- 1. 分模塊開發
- 1.1 分模塊開發設計
- 1.2 分模塊開發實現
- 1.2.1 抽取domain層
- 1.2.2 抽取dao層
- 2. 依賴管理
- 2.1 依賴傳遞
- 2.2 可選依賴
- 2.3 排除依賴
- 3. 繼承與聚合
- 3.1 聚合
- 3.2 繼承
- 3.3 總結
- 4. 屬性
- 4.1 配置文件加載屬性
- 4.2 版本管理
- 5. 多環境配置與應用
- 5.1 多環境開發
- 5.2 跳過測試
- 6. 私服
- 6.1 私服簡介
- 6.2 私服倉庫分類
- 6.3 本地倉庫訪問私服配置
- 6.4 私服資源的下載和上傳
二 小黑子的Maven高級篇學習
1. 分模塊開發
1.1 分模塊開發設計
-
按照功能拆分
-
之前的項目都是在一個模塊中,比如SSM整合,雖然這樣做,功能也都實現了,但是也存在一些問題,我們拿銀行的項目舉例,來聊聊這件事
- 網絡沒有那么發達的時候,我們需要到銀行柜臺或者取款機進行業務操作
- 隨著互聯網的發展,我們有了電腦之后,就可以在網頁上登錄銀行網站使用U盾進行業務操作
- 再來就是隨著智能手機的普及,我們只需要用手機登錄App就可以進行業務操作
-
上面三個場景出現的時間軸是不同的,如果非要把三個場景的模塊代碼放到同一個項目,那么當其中某一個模塊代碼出現問題,就會導致整個項目都無法正常啟動,從而導致銀行的多個業務都無法正常辦理,所以我們會
按照功能
將項目進行炒粉
-
-
按照模塊拆分
- 比如電商項目中,有訂單和商品兩個模塊,訂單中需要包含商品的詳細信息,所以需要商品的模型類,商品模塊也會用到商品的模型類,這個時候如果兩個模塊中都寫模型類,就會出現重復代碼,后期維護的成本就比較高。我們就想能不能把它們公共的部分抽取成一個獨立的模塊,其他模塊想要使用就可以像
導入第三方依賴
的坐標
一樣來使用我們自己抽取的模塊,這樣就解決了代碼重復的問題,這種拆分方式就是我們所說的按照模塊
拆分 - 之前的項目包結構如下
com.itheima.config
目錄存放的是相關的配置類com.itheima.controller
編寫的是Controller類com.itheima.dao
存放的是Dao接口,因為使用的是Mapper接口代理方式,所以沒有實現類包com.itheima.service
存的是Service接口,com.itheima.service.impl
存放的是Service實現類- 那我們現在就可以把這些包按照功能拆分成若干個子模塊,方便模塊之間的相互調用,接口供銷
- 這樣的話,項目中的每一層都可以單獨維護,也可以很方便的被別人使用。
- 比如電商項目中,有訂單和商品兩個模塊,訂單中需要包含商品的詳細信息,所以需要商品的模型類,商品模塊也會用到商品的模型類,這個時候如果兩個模塊中都寫模型類,就會出現重復代碼,后期維護的成本就比較高。我們就想能不能把它們公共的部分抽取成一個獨立的模塊,其他模塊想要使用就可以像
1.2 分模塊開發實現
環境準備:
復制一份之前的ssm項目,重命名為maven_01_ssm
1.2.1 抽取domain層
-
步驟一:創建新模塊
- 創建一個名為maven_02_pojo的maven項目
- 創建一個名為maven_02_pojo的maven項目
-
步驟二:項目中創建pojo包(也可以設置為domain)
- 在maven_03_pojo中創建com.itheiam.pojo包,并將maven_01_ssm的Book類拷貝到該包中
-
步驟三:刪除原項目中的pojo包
- 刪除后,maven_01_ssm項目中用到Book的類中都會爆紅
- 要想解決上述問題,我們需要在maven_01_ssm中添加maven_03_pojo的依賴。
-
步驟四:
- 在maven_01_ssm項目的pom.xml添加maven_03_pojo的依賴
<groupId>com.itheima</groupId> <artifactId>maven_02_pojo</artifactId> <version>1.0-SNAPSHOT</version>
- 因為添加了依賴,所以在maven_01_ssm中就已經能找到Book類,所以剛才的爆紅提示就會消失。
-
步驟五:直接編譯maven_01_ssm項目時
- 控制臺會報錯
Failed to execute goal on project maven_01_ssm: Could not resolve
dependencies for project com.itheima:maven_01_ssm:jar:1.0-SNAPSHOT: Could
not find artifact com.itheima:maven_03_pojo:jar:1.0-SNAPSHOT -> [Help 1]
-
意思就是找不到
maven_03_pojo
這個jar包- 為什么找不到呢?
- 原因是Maven會從本地倉庫找對應的jar包,但是本地倉庫又不存在該jar包所以會報錯。
- 在IDEA中是有
maven_03_pojo
這個項目,所以我們只需要將maven_03_pojo
項目安裝到本地倉庫即可。
- 為什么找不到呢?
-
步驟六:將項目安裝本地倉庫
-
將需要被依賴的項目maven_03_pojo,使用maven的install命令,把其安裝到Maven的本地倉庫中
-
之后再次執行maven_01_ssm的compile的命令后,就已經能夠成功編譯。
-
1.2.2 抽取dao層
-
步驟一:創建新模塊
- 創建一個名為maven_04_dao的maven項目
-
步驟二:項目中創建dao包
- 在maven_04_dao項目中創建com.itheima.dao包,并將maven_01_ssm中BookDao類拷貝到該包中
- 在maven_04_dao中會有如下幾個問題需要解決下
- 項目maven_04_dao的BookDao接口中Book類找不到報錯
- 解決方案在maven_04_dao項目的pom.xml中添加maven_04_pojo項目
<dependency><groupId>com.itheima</groupId><artifactId>maven_04_pojo</artifactId><version>1.0-SNAPSHOT</version> </dependency>
- 項目maven_04_dao的BookDao接口中,Mybatis的增刪改查注解報錯
- 解決方案在maven_04_dao項目的pom.xml中添加mybatis的相關依賴
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.6</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency>
- 最后記得使用maven的install命令,把其安裝到Maven的本地倉庫中,不下載就報錯
- 解決方案在maven_04_dao項目的pom.xml中添加mybatis的相關依賴
-
步驟三:刪除原項目中的dao包
- 刪除Dao包以后,因為maven_01_ssm中的BookServiceImpl類中有使用到Dao的內容,所以需要在maven_01_ssm的pom.xml添加maven_04_dao的依賴
-
步驟四:運行測試
- 啟動Tomcat服務器,訪問
http://localhost:8080/pages/books.html
- 將抽取后的項目進行運行,測試之前的增刪改查功能依然能夠使用。
- 啟動Tomcat服務器,訪問
如果使用maven運行tomacat7,出現報錯:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project maven_01_ssm: Compilation failure
- 可能報錯的地方:Project Structure中。 project、moudle和SDKs
修改完成之后都重新進行 install,顯示成功,所以最重要的就是jdk版本要對應起來
測試成功運行
但是有警告,解決還待商討。
2. 依賴管理
現在已經能把項目拆分成一個個獨立的模塊,當在其他項目中想要使用獨立出來的這些模塊,只需要在其pom.xml使用<dependency>
標簽來進行jar包的引入即可。
<dependency>
其實就是依賴,關于依賴管理里面都涉及哪些內容,我們就一個個來學習下:
- 依賴傳遞
- 可選依賴
- 排除依賴
先來說說什么是依賴:
-
依賴指當前項目運行所需的jar一個項目可以設置多個依賴。
-
格式為:
<!--設置當前項目所依賴的所有jar--> <dependencies> <!--設置具體的依賴--> <dependency><!--依賴所屬群組id--><groupId>org.springframework</groupId><!--依賴所屬項目id--><artifactId>spring-webmvc</artifactId><!--依賴版本號--><version>5.2.10.RELEASE</version> </dependency> </dependencies>
2.1 依賴傳遞
依賴傳遞與沖突問題:
說明:A代表自己的項目;B,C,D,E,F,G代表的是項目所依賴的jar包;D1和D2、E1和E2代表是相同jar包的不同版本
- A依賴了B和C,B和C有分別依賴了其他jar包,所以在A項目中就可以使用上面所有jar包,這就是所說的依賴傳遞
- 依賴傳遞有直接依賴和間接依賴
- 相對于A來說,A直接依賴B和C,間接依賴了D1,E1,G,F,D2和E2
- 相對于B來說,B直接依賴了D1和E1,間接依賴了G
- 直接依賴和間接依賴是一個相對的概念
- 因為有依賴傳遞的存在,就會導致jar包在依賴的過程中出現沖突問題,具體什么是沖突?Maven是如何解決沖突的?
這里所說的依賴沖突
是指項目依賴的某一個jar包,有多個不同的版本,因而造成類包版本沖突。
-
情況一:
在maven_01_ssm的pom.xml中添加兩個不同版本的Junit依賴:<dependencies> <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope> </dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope> </dependency> </dependencies>
調換位置,刷新maven面板,我們會發現,maven的dependencies面板上總是顯示使用的是后加載的jar包
于是得出一個結論:
-
特殊優先:當同級配置了相同資源的不同版本,后配置的覆蓋先配置的。
-
情況二:路徑優先
:當依賴中出現相同的資源時,層級越深,優先級越低,層級越淺,優先級越高- A通過B間接依賴到E1
- A通過C間接依賴到E2
- A就會間接依賴到E1和E2,Maven會按照層級來選擇,E1是2度,E2是3度,所以最終會選擇E1
-
情況三:聲明優先
:當資源在相同層級被依賴時,配置順序靠前的覆蓋配置順序靠后的- A通過B間接依賴到D1
- A通過C間接依賴到D2
- D1和D2都是兩度,這個時候就不能按照層級來選擇,需要按照聲明來,誰先聲明用誰,也就是說B在C之前聲明,這個時候使用的是D1,反之則為D2
-
特殊優先
:當同級配置了相同資源的不同版本,后配置的覆蓋先配置的
但是對于上面的結果,也不用刻意去記,一切以maven的dependencies面板上顯示的為準
依賴包示例圖展示:
2.2 可選依賴
依賴傳遞介紹完以后,來思考一個問題,假如
- maven_01_ssm 依賴了 maven_04_dao
- maven_04_dao 依賴了 maven_03_pojo
- 因為現在有依賴傳遞,所以maven_01_ssm能夠使用到maven_03_pojo的內容
- 如果說現在不想讓maven_01_ssm依賴到maven_03_pojo,有哪些解決方案?
說明:在真實使用的過程中,maven_01_ssm中是需要用到maven_03_pojo的,我們這里只是用這個例子描述我們的需求。因為有時候,maven_04_dao出于某些因素的考慮,就是不想讓別人使用自己所依賴的maven_03_pojo。
-
方案一:可選依賴
- 可選依賴指對外隱藏當前所依賴的資源—
不透明
- 在maven_04_dao的pom.xml,在引入maven_03_pojo的時候,添加
optional
<dependency><groupId>com.itheima</groupId><artifactId>maven_03_pojo</artifactId><version>1.0-SNAPSHOT</version><!--可選依賴是隱藏當前工程所依賴的資源,隱藏后對應資源將不具有依賴傳遞,所以最好不要true--><optional>false</optional> </dependency>
- 可選依賴指對外隱藏當前所依賴的資源—
2.3 排除依賴
-
方案二:排除依賴
- 排除依賴指主動斷開依賴的資源,被排除的資源無需指定版本—
不需要
- 前面我們已經通過可選依賴實現了阻斷
maven_03_pojo
的依賴傳遞,對于排除依賴,則指的是已經有依賴的事實,也就是說maven_01_ssm
項目中已經通過依賴傳遞用到了maven_03_pojo
,此時我們需要做的是將其進行排除,所以接下來需要修改maven_01_ssm
的pom.xml
- 排除依賴指主動斷開依賴的資源,被排除的資源無需指定版本—
<dependency><groupId>com.itheima</groupId><artifactId>maven_04_dao</artifactId><version>1.0-SNAPSHOT</version><!--排除依賴是隱藏當前資源對應的依賴關系--><exclusions><!--這里可以排除多個依賴,只要你有需求--><exclusion><groupId>com.itheima</groupId><artifactId>maven_03_pojo</artifactId></exclusion></exclusions>
</dependency>
介紹完這兩種方式后,簡單來梳理下,就是
- A依賴B,B依賴C,C通過依賴傳遞會被A使用到,現在要想辦法讓A不去依賴C
- 可選依賴是在B上設置
<optional>
,A不知道有C的存在,- 排除依賴是在A上設置
<exclusions>
,A知道有C的存在,主動將其排除掉。
3. 繼承與聚合
3.1 聚合
-
分模塊開發后,需要將這四個項目都安裝到本地倉庫,目前我們只能通過項目Maven面板的install來安裝,并且需要安裝四個,如果我們的項目足夠多,那一個個install也挺麻煩的
-
如果四個項目都已經安裝成功,當ssm_pojo發生變化后,我們就得將ssm_pojo重新安裝到maven倉庫,但是為了確保我們對ssm_pojo的修改不會影響到其他模塊(比如我們將pojo類中的一個屬性刪除,如果其他模塊調用了這個屬性,那必然報錯),我們需要對所有模塊重新編譯,看看有沒有問題。然后還需要將所有模塊再install一遍
項目少的話還好,但是如果項目多的話,一個個操作項目就容易出現漏掉或重復操作的問題,所以我們就像能不能抽取一個項目,把所有的項目管理起來,以后再想操作這些項目,做需要操作我們抽取的這個項目,這樣就省事兒多了
這就要用到我們接下來講的聚合了
- 所謂聚合:將多個模塊組織成一個整體,同時進行項目構建的過程稱為聚合
- 聚合工程:通常是一個不具有業務功能的空工程
- 作用:使用聚合工程可以將多個工程編組,通過對聚合工程的構建,實現對所包含的所有模塊進行同步構建
- 當工程中某個模塊發生更新后,必須保障工程中與更新模塊關聯的模塊同步更新,此時就可以使用聚合工程來解決批量模塊同步構建的問題
具體實現步驟如下:
- 步驟一:創建一個空的maven項目
- 步驟二:將項目打包方式改為pom
<?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><groupId>com.itheima</groupId> <artifactId>maven_00_parent</artifactId> <version>1.0-SNAPSHOT</version> <!--設置打包方式--> <packaging>pom</packaging> </project>
說明:項目的打包方式,我們接觸到的有三種,分別是
- jar:默認情況,說明該項目為java項目
- war:說明該項目為web項目
- pom:說明該項目為聚合或繼承(后面會講)項目
-
步驟三: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><groupId>com.blog</groupId> <artifactId>maven_00_parent</artifactId> <version>1.0-SNAPSHOT</version> <!--設置打包方式--> <packaging>pom</packaging><!--設置管理的項目名稱--> <modules><module>../maven_01_ssm</module><module>../maven_03_pojo</module><module>../maven_04_dao</module> </modules></project>
-
步驟四:使用聚合統一管理項目
在maven面板上點擊compile,會發現所有受管理的項目都會被執行編譯,這就是聚合工程的作用
[INFO] maven_03_pojo … SUCCESS [ 0.874 s]
[INFO] maven_04_dao … SUCCESS [ 0.044 s]
[INFO] maven_01_ssm … SUCCESS [ 0.132 s]
[INFO] maven_00_parent … SUCCESS [ 0.001 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
說明:聚合工程管理的項目在進行運行的時候,會按照項目與項目之間的依賴關系來自動決定執行的順序和配置的順序無關。
3.2 繼承
聚合工程進行某一個構建操作,其他被其管理的項目也會執行相同的構建操作。那么接下來,我們再來分析下,多模塊開發存在的另外一個問題,重復配置的問題,我們先來看張圖:
- spring-webmvc、spring-jdbc在三個項目模塊中都有出現,這樣就出現了重復的內容
- spring-test只在ssm_crm和ssm_goods中出現,而在ssm_order中沒有,這里是部分重復的內容
- 我們使用的spring版本目前是5.2.10.RELEASE,假如后期要想升級spring版本,所有跟Spring相關jar包都得被修改,涉及到的項目越多,維護成本越高
面對上面這些問題,我們就得用到接下來要學習的繼承
- 所謂繼承:描述的是兩個工程間的關系,與java中的繼承類似,子工程可以繼承父工程中的配置信息,常見于依賴關系的繼承
- 作用:
- 簡化配置
- 減少版本沖突
具體實現:
- 步驟一:創建一個空的Maven項目并將其打包方式設置為pom
<?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><groupId>com.itheima</groupId><artifactId>maven_00_parent</artifactId><version>1.0-SNAPSHOT</version><!--設置打包方式--><packaging>pom</packaging></project>
- 步驟二:在子工程中設置其父工程
<!--配置當前工程繼承自parent工程-->
<parent><artifactId>maven_00_parent</artifactId><groupId>com.itheima</groupId><version>1.0-SNAPSHOT</version><!--配置父項目的pom.xml路徑--><relativePath>../maven_00_parent/pom.xml</relativePath>
</parent>
-
步驟三:優化子項目共有依賴導入問題
- 將子項目共同使用的jar包都抽取出來,維護在父項目的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><groupId>com.itheima</groupId> <artifactId>maven_00_parent</artifactId> <version>1.0-SNAPSHOT</version> <!--設置打包方式--> <packaging>pom</packaging><!--設置管理的項目名稱--> <modules><module>../maven_01_ssm</module><module>../maven_03_pojo</module><module>../maven_04_dao</module> </modules><dependencies><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.46</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包
- 刪除完后,你會發現父項目中有依賴對應的jar包,子項目雖然已經將重復的依賴刪除掉了,但是刷新的時候,子項目中所需要的jar包依然存在。
- 當項目的
<parent>
標簽被移除掉,會發現多出來的jar包依賴也會隨之消失。
- 在父項目中修改jar包的版本,刷新后,子項目中的jar包版本也隨之變化
- 那么現在我們就可以解決了剛才提到的第一個問題,將子項目中的公共jar包抽取到父工程中進行統一添加依賴,這樣做的可以簡化配置,并且當父工程中所依賴的jar包版本發生變化,所有子項目中對應的jar包版本也會跟著更新。
-
步驟四:優化子項目依賴版本問題
如果把所有用到的jar包都管理在父項目的pom.xml,看上去更簡單些,但是這樣就會導致有很多項目引入了過多自己不需要的jar包。如上面看到的這張圖:
如果把所有的依賴都放在了父工程中進行統一維護,就會導致ssm_order項目中多引入了spring-test
的jar包,如果這樣的jar包過多的話,對于ssm_order來說也是一種"負擔"。
那針對于這種部分項目有的jar包,我們該如何管理優化呢?
-
在父工程中的pom.xml中定義依賴管理
<!--定義依賴管理--> <dependencyManagement> <dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency> </dependencies> </dependencyManagement>
-
將maven_01_ssm的pom.xml中的junit依賴刪除掉,刷新Maven
刷新后,在maven_01_ssm項目中找不到junit依賴,所以我們得出一個結論
<dependencyManagement>
標簽不真正引入jar包,而是配置可供子項目選擇的jar包依賴
子項目要想使用它所提供的這些jar包,需要自己添加依賴,并且不需要指定<version>
-
在maven_01_ssm的pom.xml添加junit的依賴
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope> </dependency>
注意:這里就千萬不需要添加版本了,這樣做的好處就是當父工程
dependencyManagement
標簽中的版本發生變化后,子項目中的依賴版本也會跟著發生變化
-
在maven_03_dao的pom.xml添加junit的依賴
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope> </dependency>
這個時候,maven_01_ssm和maven_04_dao這兩個項目中的junit版本就會跟隨著父項目中的標簽dependencyManagement
中junit的版本發生變化而變化。不需要junit的項目就不需要添加對應的依賴即可(maven_03_pojo中就沒添加)
至此繼承就已經學習完了,總結來說,繼承可以幫助做兩件事
- 將所有項目公共的jar包依賴提取到父工程的pom.xml中,子項目就可以不用重復編寫,簡化開發
- 將所有項目的jar包配置到父工程的
dependencyManagement
標簽下,實現版本管理,方便維護dependencyManagement
標簽不真正引入jar包,只是管理jar包的版本- 子項目在引入的時候,只需要指定groupId和artifactId,不需要加version
- 當
dependencyManagement
標簽中jar包版本發生變化,所有子項目中有用到該jar包的地方對應的版本會自動隨之更新
總之一句話就是,父工程主要是用來快速配置依賴jar包和管理項目中所使用的資源
。
3.3 總結
注意事項:
- 子工程中使用父工程中的可選依賴時,僅需要提供群組id和項目id,無需提供版本,版本由父工程統一提供,避免版本沖突
- 子工程中還可以定義父工程中沒有定義的依賴關系,只不過不能被父工程進行版本統一管理。
聚合與繼承的區別:
聚合與繼承分別的作用:
- 聚合用于快速構建項目,對項目進行管理
- 繼承用于快速配置和管理子項目中所使用jar包的版本
聚合和繼承的相同點:
- 聚合與繼承的pom.xml文件打包方式均為pom,可以將兩種關系制作到同一個pom文件中
- 聚合與繼承均屬于設計型模塊,并無實際的模塊內容
聚合和繼承的不同點:
- 聚合是在當前模塊中配置關系,聚合可以感知到參與聚合的模塊有哪些
- 繼承是在子模塊中配置關系,父模塊無法感知哪些子模塊繼承了自己
4. 屬性
問題分析:
前面我們已經在父工程中的dependencyManagement標簽中對項目中所使用的jar包版本進行了統一的管理,但是如果在標簽中有如下的內容:
<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>
如果我們現在想更新Spring的版本,就會發現我們依然需要更新多個jar包的版本,這樣的話還是有可能出現漏改導致程序出問題,而且改起來也是比較麻煩。
問題清楚后,我們需要解決的話,就可以參考咱們java基礎所學習的變量,聲明一個變量,在其他地方使用該變量,當變量的值發生變化后,所有使用變量的地方也會跟著變化
例如
String spring_version = "5.2.10.RELEASE";
然后將依賴的版本號替換成spring_version
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>spring_version</version>
</dependency>
解決步驟
-
步驟一:父工程中定義屬性
<properties><spring.version>5.2.10.RELEASE</spring.version><mybatis.version>3.5.6</mybatis.version> </properties>
-
步驟二:修改依賴的version
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version> </dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version> </dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version> </dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version> </dependency>
此時,我們只需要更新父工程中properties標簽中所維護的jar包版本,所有子項目中的版本也就跟著更新。當然除了將spring相關版本進行維護,我們可以將其他的jar包版本也進行抽取,這樣就可以對項目中所有jar包的版本進行統一維護
說明:使用
properties
標簽來定義屬性,在properties
標簽內自定義標簽名當做屬性名,自定義標簽內的值即為屬性值
例如:<spring.version>5.2.10.RELEASE</spring.version>
,屬性名為spring.version,屬性值為5.2.10.RELEASE
在其他地方引用變量時用${變量名}
4.1 配置文件加載屬性
新的需求,就是想讓Maven對于屬性的管理范圍能更大些,比如我們之前項目中的jdbc.properties,這個配置文件中的屬性,能不能也來讓Maven進行管理呢?
肯定的,具體的實現步驟如下:
-
步驟一:父工程定義屬性
<properties><spring.version>5.2.10.RELEASE</spring.version><mybatis.version>3.5.6</mybatis.version><jdbc.driver>com.mysql.jdbc.Driver</jdbc.driver><jdbc.url>jdbc:mysql://localhost:13306/ssm_db?useSSL=false</jdbc.url><jdbc.username>root</jdbc.username><jdbc.password>PASSWORD</jdbc.password> </properties>
-
步驟二:jdbc.properties文件中引用屬性
jdbc.driver=${jdbc.driver} jdbc.url=${jdbc.url} jdbc.username=${jdbc.username} jdbc.password=${jdbc.password}
-
步驟三:設置maven過濾文件范圍
直接在properties中引用屬性,看起來怪怪的,properties怎么能直接用到maven中配置的屬性呢?
所以我們還需要來配置一下,讓maven_01_ssm/src/main/resources
目錄下的jdbc.properties
文件可以解析${}
<build> <resources><!--設置資源目錄--><resource><!--從頂層目錄開始找起--><directory>../maven_01_ssm/src/main/resources</directory><!--設置能夠解析${},默認是false --><filtering>true</filtering></resource> </resources> </build>
-
步驟四:測試是否生效
測試的時候,只需要將maven_01_ssm項目進行打包,然后在本地倉庫觀察打包結果中最終生成的內容是否為Maven中配置的內容。-
存在的問題:
如果不只是maven_01_ssm項目需要有屬性被父工程管理,如果還有多個項目需要配置,該如何實現呢?- 方式一
<build> <resources> <!--設置資源目錄,并設置能夠解析${}--> <resource><directory>../maven_01_ssm/src/main/resources</directory><filtering>true</filtering> </resource> <resource><directory>../maven_02_pojo/src/main/resources</directory><filtering>true</filtering> </resource> ... </resources> </build>
可以一個一個配,但是項目足夠多的話,這樣還是比較繁瑣的
- 方式二
<build> <resources> <!--${project.basedir}: 當前項目所在目錄,子項目繼承了父項目,相當于所有的子項目都添加了資源目錄的過濾 --> <resource><directory>${project.basedir}/src/main/resources</directory><filtering>true</filtering> </resource> </resources> </build>
-
說明:如果打包過程中出現錯誤Error assembling WAR: webxml attribute is required
原因就是Maven發現你的項目為web項目,就會去找web項目的入口web.xml(配置文件配置的方式),發現沒有找到,就會報錯。
-
解決方案1
:在maven_02_ssm項目的src\main\webapp\WEB-INF\
添加一個web.xml文件<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"> </web-app>
-
解決方案2
: 配置maven打包war時,忽略web.xml檢查<build> <plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>3.2.3</version><configuration><failOnMissingWebXml>false</failOnMissingWebXml></configuration></plugin> </plugins> </build>
總結:
第四步了解即可
上面我們所使用的都是Maven的自定義屬性,除了${project.basedir}
,它屬于Maven的內置系統屬性。
在Maven中的屬性分為:
屬性分類 | 引用格式 | 示例 |
---|---|---|
自定義屬性 | ${自定義屬性名} | ${spring.vension} |
內置屬性 | ${內置屬性名} | b a s e d i r 、 {basedir}、 basedir、{version} |
setting屬性 | ${setting.屬性名} | ${settings.localRepository} |
ava系統屬性 | ${系統屬性分類.系統屬性名} | ${user.home} |
環境變量屬性 | ${env.環境變量屬性名} | ${env.JAVA_HOME} |
4.2 版本管理
關于這個版本管理解決的問題是,在Maven創建項目和引用別人項目的時候,我們都看到過如下內容:
<groupId>com.blog</groupId>
<artifactId>maven_00_parent</artifactId>
<version>1.0-SNAPSHOT</version><groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
這里面有兩個單詞,SNAPSHOT和RELEASE,它們所代表的含義是什么呢?
- SNAPSHOT(快照版本)
- 項目開發過程中臨時輸出的版本,稱為快照版本
- 快照版本會隨著開發的進展不斷更新
- RELEASE(發布版本)
- 項目開發到一定階段里程碑后,向團隊外部發布較為穩定的版本,這種版本所對應的構件文件是穩定的
- 即便進行功能的后續開發,也不會改變當前發布版本內容,這種版本稱為發布版本
除了上面的工程版本,我們還經常能看到一些發布版本:
- alpha版:內測版,bug多不穩定內部版本不斷添加新功能
- beta版:公測版,不穩定(比alpha穩定些),bug相對較多不斷添加新功能,相信你更新QQ的時候,一定見過QQ的beta測試版
- 純數字版
對于這些版本,我們簡單認識下即可
5. 多環境配置與應用
5.1 多環境開發
- 我們平常都是在自己的開發環境進行開發
- 當開發完成后,需要把開發的功能部署到測試環境供測試人員進行測試使用
- 等測試人員測試通過后,我們會將項目部署到生成環境上線使用。
- 這個時候就有一個問題是,不同環境的配置是不相同的,如不可能讓三個環境都用一個數據庫,所以就會有三個數據庫的url配置,
- 我們在項目中如何配置?
- 要想實現不同環境之間的配置切換又該如何來實現呢?
maven提供配置多種環境的設定,幫助開發者在使用過程中快速切換環境。具體實現步驟如下
-
步驟一:父工程配置多個環境,并指定默認激活環境
<profiles> <!--開發環境--> <profile><id>env_dep</id><properties><jdbc.url>jdbc:mysql://127.1.1.1:3306/ssm_db</jdbc.url></properties><!--設定是否為默認環境--><activation><activeByDefault>true</activeByDefault></activation> </profile> <!--生產環境--> <profile><id>env_pro</id><properties><jdbc.url>jdbc:mysql://127.2.2.2:3306/ssm_db</jdbc.url></properties> </profile> <!--測試環境--> <profile><id>env_test</id><properties><jdbc.url>jdbc:mysql://127.3.3.3:3306/ssm_db</jdbc.url></properties> </profile> </profiles>
-
步驟二:執行install查看env_dep環境是否生效
在你本地倉庫找到打包的war包,看看jdbc.properties配置文件中的url是否為jdbc:mysql://127.1.1.1:3306/ssm_db
-
步驟三:切換默認環境為生產環境
<profiles><!--開發環境--> <profile><id>env_dep</id><properties><jdbc.url>jdbc:mysql://127.1.1.1:3306/ssm_db</jdbc.url></properties></profile> <!--生產環境--> <profile><id>env_pro</id><properties><jdbc.url>jdbc:mysql://127.2.2.2:3306/ssm_db</jdbc.url></properties><!--設定是否為默認環境--><activation><activeByDefault>true</activeByDefault></activation> </profile> <!--測試環境--> <profile><id>env_test</id><properties><jdbc.url>jdbc:mysql://127.3.3.3:3306/ssm_db</jdbc.url></properties></profile> </profiles>
-
步驟四:執行install并查看env_pro環境是否生效
查看到的結果為jdbc:mysql://127.2.2.2:3306/ssm_db
雖然已經能夠實現不同環境的切換,但是每次切換都是需要手動修改,如何來實現在不改變代碼的前提下完成環境的切換呢? -
步驟五:命令行實現環境切換
在命令后加上環境idmvn install -P env_test
-
步驟六:執行安裝并查看env_test環境是否生效
查看到的結果為jdbc:mysql://127.3.3.3:3306/ssm_db
所以總結來說,對于多環境切換只需要兩步即可:
-
父工程中定義多環境
<profiles> <profile> <id>環境名稱</id><properties><key>value</key></properties><activation><activeByDefault>true</activeByDefault></activation> </profile> ... </profiles>
-
使用多環境(構建過程)
mvn 指令 -P 環境定義的ID
5.2 跳過測試
前面在執行install
指令的時候,Maven都會按照順序從上往下依次執行,每次都會執行test
,
對于test
來說有它存在的意義,
- 可以確保每次打包或者安裝的時候,程序的正確性,假如測試已經通過在我們沒有修改程序的前提下再次執行打包或安裝命令,由于順序執行,測試會被再次執行,就有點耗費時間了。
- 功能開發過程中有部分模塊還沒有開發完畢,測試無法通過,但是想要把其中某一部分進行快速打包,此時由于測試環境失敗就會導致打包失敗。
遇到上面這些情況的時候,我們就想跳過測試執行下面的構建命令,具體實現方式有很多:
-
方式一
:IDEA工具實現跳過測試
IDEA的maven面板上有一個閃電按鈕
,點擊之后可以跳過測試,不過此種方式會跳過所有的測試,如果我們想更精細的控制哪些跳過,哪些不跳過,那么就需要使用配置插件的方式來完成了
-
方式二
:配置插件實現跳過測試
在父工程中的pom.xml中添加測試插件配置<build> <plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.12.4</version><configuration><skipTests>false</skipTests><!--排除掉不參與測試的內容--><excludes><exclude>**/BookServiceTest.java</exclude></excludes></configuration></plugin> </plugins> </build>
- skipTests:如果為true,則跳過所有測試,如果為false,則不跳過測試
- excludes:哪些測試類不參與測試,即排除,針對skipTests為false來設置的
- includes:哪些測試類要參與測試,即包含,針對skipTests為true來設置的
-
方式三
:命令行跳過測試
使用Maven的命令行,mvn 指令 -D skipTests
注意事項:
- 執行的項目構建指令必須包含測試生命周期,否則無效果。例如執行compile生命周期,不經過test生命周期。
- 該命令可以不借助IDEA,直接使用cmd命令行進行跳過測試,需要注意的是cmd要在pom.xml所在目錄下進行執行。
6. 私服
6.1 私服簡介
團隊開發現狀分析
- 張三負責ssm_crm的開發,自己寫了一個ssm_pojo模塊,要想使用直接將ssm_pojo安裝到本地倉庫即可
- 李四負責ssm_order的開發,需要用到張三所寫的ssm_pojo模塊,這個時候如何將張三寫的ssm_pojo模塊交給李四呢?
- 如果直接拷貝,那么團隊之間的jar包管理會非常混亂而且容器出錯,這個時候我們就想能不能將寫好的項目上傳到中央倉庫,誰想用就直接聯網下載即可
- Maven的中央倉庫不允許私人上傳自己的jar包,那么我們就得換種思路,自己搭建一個類似于中央倉庫的東西,把自己的內容上傳上去,其他人就可以從上面下載jar包使用
- 這個類似于中央倉庫的東西就是我們接下來要學習的私服
所以到這就有兩個概念,一個是私服,一個是中央倉庫
私服
:公司內部搭建的用于存儲Maven資源的服務器遠程倉庫
:Maven開發團隊維護的用于存儲Maven資源的服務器
所以說:
- 私服是一臺獨立的服務器,用于解決團隊內部的資源共享與資源同步問題
搭建Maven私服的方式有很多,我們來介紹其中一種使用量比較大的實現方式:
- Nexus
- Sonatype公司的一款maven私服產品
- 下載地址
關于nexus的下載安裝和初次登錄
6.2 私服倉庫分類
- 在沒有私服的情況下,我們自己創建的服務都是安裝在Maven的本地倉庫中
- 私服中也有倉庫,我們要把自己的資源上傳到私服,最終也是放在私服的倉庫中
- 其他人要想使用你所上傳的資源,就需要從私服的倉庫中獲取
- 當我們要使用的資源不是自己寫的,是遠程中央倉庫有的第三方jar包,這個時候就需要從遠程中央倉庫下載,每個開發者都去遠程中央倉庫下速度比較慢(中央倉庫服務器在國外)
- 私服就再準備一個倉庫,用來專門存儲從遠程中央倉庫下載的第三方jar包,第一次訪問沒有就會去遠程中央倉庫下載,下次再訪問就直接走私服下載
- 前面在介紹版本管理的時候提到過有
SNAPSHOT
和RELEASE
,如果把這兩類的都放到同一個倉庫,比較混亂,所以私服就把這兩個種jar包放入不同的倉庫 - 上面我們已經介紹了有三種倉庫,一種是存放
SNAPSHOT
的,一種是存放RELEASE
還有一種是存放從遠程倉庫下載的第三方jar包,那么我們在獲取資源的時候要從哪個倉庫種獲取呢? - 為了方便獲取,我們將所有的倉庫編成一個組,我們只需要訪問倉庫組去獲取資源。
所有私服倉庫總共分為三大類:
- 宿主倉庫hosted
- 保存無法從中央倉庫獲取的資源
- 自主研發
- 第三方非開源項目,比如Oracle,因為是付費產品,所以中央倉庫沒有
- 代理倉庫proxy
- 代理遠程倉庫,通過nexus訪問其他公共倉庫,例如中央倉庫
- 倉庫組group
- 將若干個倉庫組成一個群組,簡化配置
- 倉庫組不能保存資源,屬于設計型倉庫
倉庫類別 | 英文名稱 | 功能 | 關聯操作 |
---|---|---|---|
宿主倉庫 | hosted | 保存自主研發+第三方資源 | 上傳 |
代理倉庫 | proxy | 代理連接中央倉庫 | 下載 |
倉庫組 | group | 為倉庫編組簡化下載操作 | 下載 |
6.3 本地倉庫訪問私服配置
- 我們通過IDEA將開發的模塊上傳到私服,中間是要經過本地Maven的
- 本地Maven需要知道私服的訪問地址以及私服訪問的用戶名和密碼
- 私服中的倉庫很多,Maven最終要把資源上傳到哪個倉庫?
- Maven下載的時候,又需要攜帶用戶名和密碼到私服上找對應的倉庫組進行下載,然后再給IDEA
- 上面所說的這些內容,我們需要在本地Maven的配置文件settings.xml中進行配置。
-
步驟一:私服上配置倉庫
新建兩個倉庫,type選hosted,version policy 一個選release,一個選snapshot
-
步驟二:配置本地Maven對私服的訪問權限
<servers> <server> <!--id私服中的服務器名稱,就是剛剛創建的倉庫名--><id>itheima-snapshot</id><username>admin</username><password>admin</password> </server> <server><id>itheima-release</id><username>admin</username><password>admin</password> </server> </servers>
-
步驟三:配置私服的訪問路徑
自定義不在范圍內打要拖拽過來<mirror><!--配置倉庫組的ID--><id>maven-public</id><!--*代表所有內容都從私服獲取--><mirrorOf>*</mirrorOf><!--私服倉庫組maven-public的訪問路徑--><url>http://localhost:8081/repository/maven-public/</url> </mirror>
6.4 私服資源的下載和上傳
本地倉庫與私服已經建立了連接,接下來我們就需要往私服上上傳資源和下載資源,具體的實現步驟如下
-
步驟一:配置工程上傳私服的具體位置
<!-- 配置當前工程保存在私服中的具體位置--> <distributionManagement><repository><id>itheima-release</id><url>http://localhost:8081/repository/itheima-release/</url></repository><snapshotRepository><id>itheima-snapshot</id><url>http://localhost:8081/repository/itheima-snapshot/</url></snapshotRepository></distributionManagement>
-
步驟二:發布資源到私服
maven面板中運行deploy
,或者執行maven命令mvn deploy
注意:
- 要發布的項目都需要配置
distributionManagement
標簽,要么在自己的pom.xml中配置,要么在其父項目中配置,然后子項目中繼承父項目即可。- 如果報401錯誤,嘗試將maven的setting.xml文件復制到
C:\Users\username\.m2
目錄下,然后在重新進行deploy
但是個人有個小報錯,發現maven_04_dao出現依賴循環了,在maven_00_parent文件中,把其注釋掉就不會報錯Process terminated
的類型
發布成功,在私服中就能看到了
現在發布是在blog-snapshot倉庫中,如果想發布到blog-release倉庫中就需要將項目pom.xml中的version修改成RELEASE即可。
<groupId>com.itheima</groupId>
<artifactId>maven_00_parent</artifactId>
<!--<version>1.0-SNAPSHOT</version>-->
<version>1.0-RELEASE</version>
如果私服中沒有對應的jar,會去中央倉庫下載,速度很慢。可以配置讓私服去阿里云中下載依賴。
修改maven-central的Remote storage為私服去阿里云中下載依賴
至此私服的搭建就已經完成,相對來說有點麻煩,但是步驟都比較固定