顏羣老師講解,視頻地址:https://ke.qq.com/course/303156?taid=2222959108595764
一片很明白的博文:https://blog.csdn.net/qq_25827845/article/details/78988909
- maven 簡介:
Maven 翻譯爲"專家"、"內行",是 Apache 下的一個純 Java 開發的開源項目。基於項目對象模型(縮寫:POM)概念.
自動化構建工具(其它的類似的這種工具 make-ant-maven-gradle) gradle最新,但是學習難度大
- maven作用:
Maven 是一個項目管理工具,可以對 Java 項目進行構建、依賴管理。
i: jar包管理(依賴管理)
說明: Maven在進行配置好gav(座標)之後,運行相應的命令後自動給我們下載jar包,但是有很多的包都是依賴別的jar包的,比如commons-fileupload.jar 會關聯comments-io 包,有了Maven,它會自動關聯下載所有依賴的Jar,並且不會衝突,this is the NB for Maven。
ii: 將項目拆分成若干個模塊
說明:爲什麼這麼幹 ?因爲很多互聯網公司的項目都是一個十分巨大和複雜的工程,我們不止可以對項目進行分層,還可以將一個巨大的項目進行拆分,拆成多個比較小的項目,如下圖,一個項目可分多層,比如UI層,Service層和Dao層等,隨着項目的跟進,每一層代碼都很大,整個項目就特別大,然後就想起來把一個大項目分解成多個小項目,Maven就是可以實現。
- maven具體功能
清理clean:刪除編譯的結果,爲重新編譯做準備。
編譯compile:java->class 類到class文件的過程
測試test: 針對於項目中的關鍵點進行測試,亦可用項目中的測試代碼去測試開發代碼;
報告:有測試就有報告,將測試的結果進行顯示
打包package: 將項目中包含的多個文件壓縮成一個文件, 用於安裝或部署。 (java項目爲-jar、web項目-war,war包可以放在web容器內直接運行)
安裝install:將打成的包,放到本地倉庫,供其他項目使用。比如a,b,c三個項目,dao,service,ui,三個項目有依賴,將三個項目打成包放到本地倉庫供其它去使用
部署deploy:將打成的包 ,放到服務器上準備運行。
所以來說:Maven就是將原產品變成可發佈的項目,將java、js、jsp等各個文件 進行篩選、組裝,變成一個 可以直接運行的項目。
- maven倉庫:
引入倉庫的原因:
eg 我的計算機上有多個A,B,C項目,然後我這三個項目都需要abc.jar,如果沒有一個公共的存儲jar包的地方,每一個項目在進行引入jar包的時候都需要進行聯網進行下載jar包,比較費時間,費事費力費空間。Maven的做法是在我們的計算機內,開闢一片空間,一個文件夾內,把所有通過Maven進行管理的項目中需要的jar包,放在一起進行存儲,A項目運行的時候需要abc.jar,首先去本地倉庫進行尋找,如果有直接下載到項目裏,沒有再去中央倉庫(遠程倉庫)進行查找並下載,當B項目在運行的時候需要abc.jar,會先去本地倉庫查找,如果有就直接拿來下載到項目,沒有就去遠程中央倉庫進行下下載。
本地倉庫:在本機上,maven存儲jar包的地方,
遠程倉庫:私服(見最後附件),中央倉庫、其他公用庫等
倉庫還有一種結構: 可以通過nexus進行私服的架構 ,多一種選擇模式。
- 本機maven環境設置:
下載配置maven
Binary:二進制 Source:源代碼 Zip是windows Gz是Linux
下載到本地硬盤上,壓縮版解壓就行,我放在了D盤根目錄:
a.配置JAVA_HOME
b.配置MAVEN_HOME : D:\apache-maven-3.5.3\bin 【M2_HOME(或者配置這個)】
c.配置path : %MAVEN_HOME%\bin
d.驗證 : mvn -v
e.配置本地倉庫 maven目錄/conf/settings.xml
默認本地倉庫 :C:/Users/YANQUN/.m2/repository
修改本地倉庫爲: <localRepository>D:/loc_lib</localRepository>
默認的本地倉庫沒改之前是下面這個樣子: 我的電腦上就是 user/zqbig/.m2/repository
- maven相關約定
首先需要知道一個事情,約定優於配置
三種方式:【硬編碼的方式(寫死代碼),配置的方式(xml配置),約定方式】
Maven約定的目錄結構如下
maven約定的目錄結構: 項目 -src ----main 【程序功能代碼】 ----java 【java代碼 (Hello xxx)】 ----resources 【資源代碼、配置代碼】 ----test 【測試代碼】 ----java ----resources -target 【將源碼編譯後的結果放在這個文件夾下】
pom.xml 【和src同級目錄,項目對象模型】 |
講一下什麼是pom:project object module 項目對象模型 ,不同於面向對象等相關思想,將項目看成節點或者對象,
<groupId>域名翻轉.大項目名</groupId>
<artifactId>子模塊名</artifactId>
<version>版本號</version>
<groupId>org.lanqiao.maven</groupId>
<artifactId>HelloWorld</artifactId>
<version>0.0.1-SNAPSHOT</version>
在創建好相關項目後,並編寫pom文件,執行Maven命令常用命令,我們在pom所在目錄至此那個cmd操作
: 注意必須和項目中的pom是同級目錄才能執行。
mvn compile :進行項目編譯,首次執行會去本地倉庫根據本地倉庫gav找依賴的jar,有就直接拿來用,沒有去中央找,然後再用。compile只編譯main目錄,會忽略Test目錄中的代碼
其它命令:
mvn test :進行測試編碼的編譯,出現上圖的代碼,說明編譯成功了
mvn package: 進行打包,只有在通過測試之後,才能進行打包。如果只是java文件,那麼就打成了jar包,如果是web項目,則會打包成war包
mvn install: 打包之後,通過mvn install 將打好的包安裝到本地倉庫,供其它項目或者模塊使用。
mvn clean:刪除target目錄(刪除編譯文件的目錄)
運行mvn命令,必須在pom.xml文件所在目錄
- maven生命週期(瞭解):
生命週期和構建的關係:生命週期中的順序:a b c d e
當我們執行c命令,則實際執行的是 a b c
clean lifecycle :清理分成三個階段:1:pre-clean 2.clean 3.post-clearn
default lifecycle :默認(常用)site lifecycle:站點 和發佈站點有關
pre-site site post-site site-deploy(部署)
再次強調:在pom.xml中增加完依賴後 需要maven - update project
- Maven
最重要的部分:依賴
1.依賴的有效範圍
在pom文件中 dependency 的 scope標籤就是依賴範圍 。
Maven在編譯、測試、運行項目時,各自使用一套classpath,所以依賴jar的scope定義了依賴的範圍,定義了有效性的範圍
例如:A 項目依賴於Junit的相關jar包
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>test</scope>
</dependency>
test就是在測試的時候可以拿到A.jar,然後在compile 和其它
- compile: 編譯依賴範圍(Default,大多數情況下我們都是在使用compile編譯範圍)
- test: 測試依賴範圍 (編譯主代碼和運行時無效)
- provided: 已提供依賴範圍(就是說在運行的時候容器已經給我們提供該依賴了,比如說servlet-api)
provided 具體案例:servlet-api.jar ,這個jar在我們開發的時候需要引入,在測試的時候也需要用到,但在部署和運行的時候,web容器自帶這個jar包,所以在運行的時候是不需要依賴拿到這個jar的。
2.依賴的傳遞性
eg:A->b->c A依賴於B,B依賴於C,如果試A依賴於C成立,則需要B依賴於C的範圍必須是compile
3.依賴調解
eg.HelloWorldTime ->HelloWorld2 ->junit
看上面的例子,如果兩個項目都引入的Junit ,那麼maven是如何來避免 Jar衝突的呢。
兩個原則,原則一:路徑最短,
如下圖:HelloWorldTime 依賴於HelloWorld,然後HelloWorld依賴於junit4.0。然而HelloWorldTime自己有添加的依賴Juit3.8 ,這個時候Maven 會在HelloWorldTime選擇用哪個呢?答案是Junit3.8。
原則二:路徑長度相同的
如下這種情況:
i.在同一個pom.xml文件中有2個相同的依賴(覆蓋):後面聲明的依賴 會覆蓋前面聲明的依賴 (嚴禁使用本情況,嚴禁在同一個pom中聲明2個版本不同的依賴)
ii.如果是不同的 pom.xml中有2個相同的依賴(優先):則先聲明的依賴 ,會覆蓋後聲明的依賴
存在:A->-B>-C->X(1.0)和A->D->X(2.0)
原則:路徑最近原則(指依賴通過幾層傳遞性依賴引入),X(2.0)將會被解析
存在:A->B->Y(1.0)和A->C->Y(2.0)
原則:第一聲明優先原則,哪個現在pom中聲明(也就是在pom文件的上邊),
就以哪個爲準(Maven2.0.9開始使用,在此之前是不確定的,導致構建項目具有一定的隨機性)
3. 依賴排除:
我們通過在pom中配置<dependency></dependency>來引入依賴,但是該依賴存在多個傳遞性依賴,如果某個間接依賴不是我們需要的,影響到了我們項目的正常構建,那麼我們可以使用<exclusions><exclusion></exclusion></exclusions>來幹掉它。示例如下:
<dependency>
<groupId>com.xx.miliao</groupId>
<artifactId>xx-serviceapi</artifactId>
<exclusions>
<exclusion>
<artifactId>xx-thrift-micloud-common</artifactId>
<groupId>com.xx</groupId>
</exclusion>
<exclusion>
<artifactId>thrift</artifactId>
<groupId>org.apache.thrift</groupId>
</exclusion>
<exclusion>
<groupId>com.xx</groupId>
<artifactId>ipWrapper</artifactId>
</exclusion>
</exclusions>
</dependency>
在上邊的配置中,我們引入了xx-serviceapi的依賴,但是我們將該依賴所引入的org.apache.thrift和ipWrapper依賴都給排除掉了,這兩個依賴將不會出現在我們構建的項目中。
4.歸類依賴: 通過Maven統一配置各需要jar和plugs等內容的的版本, 歸類依賴看着高大上,其實說白了就是爲了統一簡單的管理依賴版本,如果某些依賴的version都是一致的或者是存在某些特殊的關係,我們可以在pom中使用<properties></properties>配置一些變量,在下邊的時候使用$變量名來搞定。
這個profiles 可以配置jdk等很多屬性,也可以對一些依賴的版本號進行配置 ,比如統一編碼,
比如下方爲某個項目中對junit版本進行統一配置,通過properties下設置標籤和標籤內容來設定 版本,然後在進行配置依賴的時候,version就可以選擇已經定義好的值。
通過maven統一jdk版本:
<profiles>
<profile>
<id>jdk-18</id> 版本號
<activation>
<activeByDefault>true</activeByDefault> 激活
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
對於依賴傳遞性的問題 :A-->B-->Junit 這種集成關係,如果希望A也依賴於Jnit ,那麼需要B和Junit的依賴範圍爲compile.這就很麻煩。
Maven 提出了一種 繼承的概念
在上邊的學習中,我們介紹了Maven是一種強大的構建工具,能夠幫助我們自動下載構件,並且通過給每一個構件確定其座標,實現了構件在倉庫中的存儲。正是Maven的生命週期和插件的互相綁定才使得我們可以非常愉快的完成項目的構建。在實際的項目中,我們往往會建立多個模塊(module)。我們在本文中要介紹的聚合和繼承就特別適合多個模塊的協同工作。[摘抄]
Maven的繼承特性可以將各個模塊相同的依賴和插件配置提取出來,在簡化POM的同時還可以促進各個模塊配置的一致性。
eg: A-->B ,A繼承與B,則 B是一個父類的存在,
A會繼承所有B 的依賴。 在創建B的時候我們稱之爲父工程,在創建的時候父工程不需要進行編碼之類的東西,只添加依賴,所以在父工程的打包類型packageing選擇 pom類型(java是jar,web項目是war)
父工程可以用來添加所有的依賴,子工程用來實際編碼,不用每個工程都添加相應的依賴【可不可以?】
B的pom文件
父工程的pom.xml中多了這麼一個標籤:
子工程需要怎麼操作?
需要在子工程中的配置父工程的gav座標,你還得告訴子工程你有爹了
標籤<parent></parent>就是用來告訴他有爹了。
如果在配置的時候,父工程的groupId和version等屬性 如果相同,在子工程裏,其實這些信息可以省略,因爲他會繼承父工程的。
這個繼承的時候和類繼承類似,在上面我們進行依賴性的測試時,如果A-->B-->junit
原來單純依賴的時候,B依賴於Junit的時候範圍爲compile,那麼在A工程的類包中可以看到junit的jar,
但是在繼承的時候不一樣,我們會看不到。但是有時候父工程的依賴特別多,我們並不想全盤接受。
繼承實現步驟:
1.建立父工程: 父工程的打包方式爲pom
2.在父工程的pom.xml中編寫依賴:
<dependencyManagement>
<dependencies>
<dependency>
3.子類:
<!-- 給當前工程 繼承一個父工程:1加入父工程座標gav 2當前工程的Pom.xml到父工程的Pom.xml之間的 相對路徑 -->
<parent>
<!-- 1加入父工程座標gav -->
<groupId>org.lanqiao.maven</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 2當前工程的Pom.xml到父工程的Pom.xml之間的 相對路徑 -->
<relativePath>../B/pom.xml</relativePath>
</parent>
4.在子類中 需要聲明 :使用那些父類的依賴
<dependency>
<!-- 聲明:需要使用到父類的junit (只需要ga) -->
Maven的聚合特性可以幫助我們把項目的多個模塊聚合在一起,使用一條命令進行構建,即一條命令實現構建多個項目;
我們在一個項目中會存在模塊A和模塊B,在各自的項目目錄下,我們可以分別通過命令 mvn clean package 來構建各個模塊,但是如果我們想將這兩個模塊一起構建呢?
答案是我們需要建立一個模塊C做爲一個聚合模塊。
C模塊的打包方式必須爲pom。
聚合模塊和父模塊經常可以做到合二爲一。
eg.項目HelloWorld2與 項目HelloWorldTime, 如果想讓這兩個項目,第一個項目中的類,第二個類可以用,那麼可以把HelloWorld 打成包,放在本地倉庫中,然後在第二個項目HelloWorldTime 項目的pom中,添加這個項目的依賴。
HelloWorld2 中pom定義的項目座標如下:
在執行完 install之後,我們可以從本地倉庫D:/loc_lib/org/lanqiao/maven/下 找到要生成的jar包
然後在HelloWorldTime中的pom進行依賴引入;如下: 上部紅色框是HelloWorldTime 自己的,下面是依賴的HelloWorld的
用Myeclipse 創建一個Maven項目,空白處右鍵
在eclipse中創建Maven工程,需要進行配置,修改本地的倉庫。
eclipse會自帶Maven,我們進行選擇自己安裝的Maven。
更換之後,在下面會有一個user Settings
瀏覽選擇自己Maven安裝路徑conf目錄下的 settings.xml(這裏面有我們配置的<localRepository>D:/loc_lib</localRepository>);
選中之後,最下面的Local Repository 會自動的變成 我們本地倉庫的目錄。