Maven自動(dòng)化構(gòu)建工具

Maven是Apache軟件基金會(huì)的一個(gè)開源項(xiàng)目,用來處理Java工程的自動(dòng)化構(gòu)建,它有兩個(gè)主要特征:

  • 構(gòu)建
  • 自動(dòng)化處理依賴關(guān)系

構(gòu)建就是將源代碼恨闪、第三方的依賴包(jar包)优质、各種資源和配置打包成為一個(gè)可執(zhí)行文件(如war包)的過程。現(xiàn)在的高級(jí)IDE研叫,比如IDEA,Eclipse都有自動(dòng)化構(gòu)建的功能璧针,我們只需要點(diǎn)一下run按鈕蓝撇,IDE就會(huì)自動(dòng)的幫我們構(gòu)建項(xiàng)目,并部署IDE內(nèi)置的容器(Tomcat)中陈莽,供我們預(yù)覽和調(diào)試渤昌。

既然有了這些高級(jí)IDE,為什么Maven還存在呢走搁?實(shí)際上Maven項(xiàng)目建立之初独柑,還沒有這些高級(jí)的IDE,關(guān)于自動(dòng)構(gòu)建工具的發(fā)展史如下:

自動(dòng)構(gòu)建工具發(fā)展史

其中Maven取代Ant的時(shí)候私植,高級(jí)的IDE還沒有出現(xiàn)忌栅,現(xiàn)在即使有這些高級(jí)的IDE,它也僅僅是解決了在開發(fā)階段自動(dòng)構(gòu)建的問題曲稼,并沒有解決項(xiàng)目的依賴問題索绪,更何況是在DevOps中的持續(xù)交互和持續(xù)集成。

1 Maven安裝與配置

要運(yùn)行Maven需要下載JDK贫悄,這里不做JDK的安裝的介紹瑞驱。

Maven官網(wǎng)下載Maven后,解壓到指定的目錄,這里我放在了/usr/local/maven目錄下窄坦。然后做Mac系統(tǒng)環(huán)境變量配置唤反,在/etc/paths.d目錄下新建maven文件凳寺,寫入maven目錄的路徑,需要切換到root用戶彤侍。

echo "/usr/local/maven/bin" > /etc/paths.d/maven

使用mvn -v查看Maven的信息:

mvn -v
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T02:41:47+08:00)
Maven home: /usr/local/maven
Java version: 1.8.0_151, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "mac os x", version: "10.14", arch: "x86_64", family: "mac"

使用tree命令查看Maven的目錄結(jié)構(gòu):

# Maven的目錄結(jié)構(gòu)
tree -L 1 /usr/local/maven/
/usr/local/maven/
├── LICENSE
├── NOTICE
├── README.txt
├── bin
├── boot
├── conf
└── lib

比較重要的是conf/setting.xml文件肠缨,它是Maven的配置文件,有以下幾個(gè)標(biāo)簽需要注意:

  • localRepository 表示的Maven本地倉(cāng)庫(kù)的位置盏阶,默認(rèn)值是${user.home}/.m2/repository晒奕,及當(dāng)前用戶根目錄下。倉(cāng)庫(kù)的概念放在后面說名斟,這里大概知道是用來存放從網(wǎng)上下載下來的第三方j(luò)ar包的吴汪。
  • mirrors 表示要從哪里下載第三方j(luò)ar,及中央倉(cāng)庫(kù)的鏡像(后面說)蒸眠,Maven的中央倉(cāng)庫(kù)在國(guó)外,一般為了提高下載速度杆融,我們都會(huì)配置國(guó)內(nèi)的鏡像楞卡,這里我配置了阿里云的鏡像,也可以配置多個(gè)鏡像脾歇。
<mirrors>
    <mirror>
          <id>alimaven</id>
          <name>aliyun maven</name>
          <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
          <mirrorOf>central</mirrorOf>        
    </mirror>
</mirrors>

2 構(gòu)建過程

Maven的構(gòu)建過程大致分為以下步驟:

構(gòu)建階段
  • Clean 清空編譯結(jié)果蒋腮,為下一次編譯做準(zhǔn)備
  • Compile 編譯主程序源文件,Maven將源文件分為主程序源文件和測(cè)試程序源文件藕各,他們放在不同的目錄
  • Test 編譯測(cè)試程序源文件
  • Package 將主程序編譯后的class文件池摧、資源文件以及配置文件,打包為對(duì)應(yīng)的類型(jar包或war包激况,需要在pom.xml中設(shè)置)
  • Install 將打包后的文件按照一定規(guī)則(groupId+artifactId的方式)安裝到本地倉(cāng)庫(kù)中
  • Deploy 部署程序

構(gòu)建過程是按上面的順序依次進(jìn)行的作彤,我們可以通過IDE或CLI選擇執(zhí)行到某一步。比如我們選擇執(zhí)行package打包這一步乌逐,Maven會(huì)先執(zhí)行package前面的所有步驟竭讳,最后才做打包這個(gè)步驟,也就是說浙踢,不管我們要執(zhí)行哪一個(gè)步驟绢慢,Maven都會(huì)從Clean開始,順序往后執(zhí)行到我們選擇的那一步洛波。

通過CLI的方式執(zhí)行構(gòu)建命令時(shí)胰舆,只需在項(xiàng)目的根目錄輸入mvn后面加要執(zhí)行到的步驟即可。例如蹬挤,要執(zhí)行到打包(package)這一步缚窿,可在項(xiàng)目的根目錄中輸入以下命令:

mvn package

3 Maven工程目錄結(jié)構(gòu)

Maven工程采用約定大于配置(Convention over Configuration)的設(shè)計(jì),及源文件放哪個(gè)目錄焰扳,測(cè)試文件放哪個(gè)目錄是約定好了的滨攻,如果不按這個(gè)約定存放够话,那么Maven會(huì)不能正確的構(gòu)建這個(gè)項(xiàng)目。

maven_webApp
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   ├── resrouce
    │   └── webapp
    │       ├── WEB-INF
    │       │   └── web.xml
    │       └── index.jsp
    └── test
        ├── java
        └── resource

上面是Maven WebApp的一個(gè)目錄結(jié)構(gòu)光绕,在根目錄下有一個(gè)src目錄和pom.xml文件女嘲,pom.xml 是Maven工程的標(biāo)志,可以簡(jiǎn)單的理解為只有有了pom.xml文件诞帐,這個(gè)工程才是Maven工程欣尼。

src目錄下面有main目錄和test目錄,分別用來存放主程序和測(cè)試程序停蕉,其下面又分為javaresource目錄愕鼓,java目錄用來存放源碼文件低缩,resource目錄用來存放資源文件望门。如果是webapp的工程,建議(非強(qiáng)制約定)在main目錄下添加webapp的目錄呆万,用來存放于web相關(guān)的資源蚓挤。

4 倉(cāng)庫(kù)與坐標(biāo)

4.1 倉(cāng)庫(kù)

倉(cāng)庫(kù)是用來存放東西的磺送,方便我們引用,這些東西大致可以分類3類:

  1. 存放Maven構(gòu)建過程需要的plugin灿意,Maven核心程序僅定義了構(gòu)建的接口估灿,具體的實(shí)現(xiàn)是由單獨(dú)的plugin完成的。比如pom.xml文件中定義如下的plugin插件

    <build>
        <pluginManagement>
            <plugin>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.8.0</version>
            </plugin>
        </pluginManagement>
    </build>
    

    maven-compiler-plugin是Maven的編譯插件缤剧,在執(zhí)行mvn compile命令時(shí)馅袁,由Maven核心程序調(diào)用。它存放在~/.m2/repository/org/apache/maven/plugins/maven-compiler-plugin目錄中荒辕。

  2. 存放通過mvn install命令安裝的本地工程

  3. 存放第三方的jar包

倉(cāng)庫(kù)按位置又可以分為:本地倉(cāng)庫(kù)汗销,私有倉(cāng)庫(kù),中央倉(cāng)庫(kù)以及中央倉(cāng)庫(kù)鏡像抵窒。比如大溜,我們需要引用一個(gè)jar包,Maven會(huì)先在本地倉(cāng)庫(kù)查找估脆,如果沒有钦奋,就到私有倉(cāng)庫(kù)中找,私有倉(cāng)庫(kù)有該包疙赠,將該jar包下載到本地倉(cāng)庫(kù)付材;如果私有倉(cāng)庫(kù)沒有,就從中央倉(cāng)庫(kù)(鏡像)中下載該包到私有倉(cāng)庫(kù)和本地倉(cāng)庫(kù)圃阳。這里私有倉(cāng)庫(kù)并不是必須的厌衔,一般有條件的企業(yè)會(huì)通過Nexus等軟件自行搭建一個(gè)私有倉(cāng)庫(kù),以方便企業(yè)內(nèi)部開發(fā)者對(duì)jar包的引用捍岳。中央倉(cāng)庫(kù)的鏡像的目錄是提升jar包的下載速度富寿。

4.2 坐標(biāo)

坐標(biāo)是jar包的元數(shù)據(jù)睬隶,用來描述jar包在倉(cāng)庫(kù)中的位置。包括groupId組織名稱页徐,artifactId項(xiàng)目名稱苏潜,version信息等,通過這三個(gè)屬性变勇,Maven就能準(zhǔn)確的找到該包恤左。比如,程序中要引用mysql驅(qū)動(dòng)搀绣,可以在pom.xml文件中添加如下的配置(依賴)飞袋,該配置中包含了坐標(biāo)信息,Maven將通過這個(gè)坐標(biāo)找到對(duì)應(yīng)的jar包链患。

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

5 依賴

我們創(chuàng)建了一個(gè)項(xiàng)目A巧鸭,如果它要完成某些工作,需要引入項(xiàng)目B麻捻,那么我們就說A依賴于B纲仍。在沒有用Maven時(shí),我們需要手動(dòng)的將B復(fù)制到項(xiàng)目A中芯肤,并添加引用關(guān)系。使用Maven后压鉴,我們只需在pom.xml文件中做如下配置即可崖咨,Maven會(huì)為我們下載對(duì)應(yīng)坐標(biāo)的包,以及添加引用油吭。

<dependency>
  <groupId>組織名稱</groupId>
  <artifactId>項(xiàng)目名稱</artifactId>
  <version>版本號(hào)</version>
</dependency>

如果B又依賴C击蹲,那么A就間接依賴C。為了區(qū)分間接依賴婉宰,我們也可以說A是直接依賴B歌豺,如下圖所示:

maven依賴

Maven會(huì)將B加入工程A中,而項(xiàng)目C作為A的間接依賴心包,也為加入到A中类咧,我們叫這種情況為依賴傳遞。

5.1 依賴傳遞原則

依賴傳遞的原則:就近原則+聲明先后原則蟹腾。

考慮如下情況:

maven-依賴

項(xiàng)目C有兩個(gè)版本痕惋,分別是V1和V2版本。項(xiàng)目A直接依賴B和C V2版本娃殖,B直接依賴C的V1版本值戳,此時(shí)Maven會(huì)通過就近原則添加C V2版本。就近原則基本是按步長(zhǎng)來計(jì)算的炉爆,那什么是步長(zhǎng)呢堕虹?比如A到C V2只要一步卧晓,而A到C V1需要通過B,及A到B為一步赴捞,B到C V1是一步逼裆,總計(jì)2步,所以A到C V2的步長(zhǎng)小于A到CV1螟炫,此時(shí)Maven會(huì)添加C V2到項(xiàng)目中波附。

如果A到達(dá)C的兩個(gè)版本的步長(zhǎng)是相同的,Maven會(huì)按pom中的定義的先后順序加入對(duì)應(yīng)的依賴昼钻,先定義的會(huì)加入到A的依賴中掸屡。

maven依賴

上面兩種情況,A到C的步長(zhǎng)是相同的然评,Maven會(huì)更加定義的先后順序添加C仅财,因?yàn)镃1比C2先定義,所以Maven不會(huì)添加C2版本碗淌。

5.2 依賴排除

依賴排除是通過配置pom.xml文件盏求,實(shí)現(xiàn)對(duì)間接依賴的排除,這個(gè)不是常用亿眠。具體的做法是在dependency標(biāo)簽中使用exclusions標(biāo)簽

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>4.3.22.RELEASE</version>
  <exclusions>
    <exclusion>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
    </exclusion>
  </exclusions>
</dependency>

我們知道spring-core模塊依賴commons-logging模塊做日志輸出碎罚,如果我們不希望加載commons-logging,可以使用上面的配置將logging排除在依賴之外纳像。

5.3 依賴的范圍

依賴的范圍和構(gòu)建的階段(過程)是密不可分的荆烈,Maven使用scope標(biāo)簽來標(biāo)識(shí)依賴的范圍,

  • compile - scope的默認(rèn)值竟趾,標(biāo)識(shí)依賴在整個(gè)生命周期都適用憔购。

  • provided - 僅在編譯和測(cè)試階段有效,它不做依賴的傳遞岔帽。比如我們?cè)陂_發(fā)web app時(shí)玫鸟,在開發(fā)階段我們需要引用servlet-api的jar包,而當(dāng)我們部署app到tomcat容器時(shí)犀勒,tomcat容器為我們提供了servlet-api的jar包屎飘,如果我們將引用的servlet-api打包到war包中,就會(huì)與容器的jar沖突贾费。此時(shí)我們可以標(biāo)記servlet-api為provided枚碗,使servlet-api這個(gè)jar包只在編譯和測(cè)試階段有效,而我們?cè)诖虬?xiàng)目時(shí)铸本,將該jar排除在外肮雨,以解決沖突。

    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    
  • runtime - 這個(gè)scope的范圍表示依賴不在參與編譯階段箱玷,這個(gè)依賴是服務(wù)于執(zhí)行階段的怨规,這個(gè)很少用到陌宿。

  • test - 僅在編譯和測(cè)試階段有效,不參與打包等其他階段波丰,標(biāo)記為test的依賴不會(huì)做依賴傳遞壳坪。

  • system - 與 provided相似, 只是這個(gè)依賴包不會(huì)從倉(cāng)庫(kù)中查找掰烟,這個(gè)也很少用到爽蝴。

源碼編譯階段 測(cè)試源碼編譯階段 打包階段 部署階段
compile ? ? ? ?
test ? ? - -
provided ? ? - -

注意test和provided的區(qū)別:test在源碼編譯和測(cè)試源碼編譯都會(huì)參與,這個(gè)依賴包只是做測(cè)試用的纫骑,后面打包部署的時(shí)候不會(huì)添加該依賴包蝎亚,容器中也不會(huì)提供該依賴包;provided在源碼編譯和測(cè)試源碼編譯都會(huì)參與先馆,打包的時(shí)候发框,也不會(huì)加入該依賴包。但是煤墙,一般是tomcat等容器會(huì)提供該依賴包梅惯。

6 POM

上面零散的說了些POM的內(nèi)容,并沒有提到POM的概念仿野,這里補(bǔ)充一下铣减,POM(Project Object Model)翻譯過來是項(xiàng)目對(duì)象模型。我們可以將POM項(xiàng)目對(duì)象模型分開理解脚作,一個(gè)Maven工程就是一個(gè)項(xiàng)目對(duì)象葫哗,比如,一個(gè)Maven的java工程和一個(gè)Maven的web工程鳖枕,他們都是一個(gè)獨(dú)立的項(xiàng)目對(duì)象魄梯。知道了項(xiàng)目對(duì)象后桨螺,我們對(duì)項(xiàng)目對(duì)象進(jìn)行抽象宾符,建立一個(gè)模型,用這個(gè)模型來描述這個(gè)Maven工程灭翔,我們這個(gè)模型是POM項(xiàng)目對(duì)象模型魏烫。

我們抽象出來的模型總的有個(gè)地方存,存在個(gè)模型的文件就是pom.xml肝箱,也可說POM的具體表現(xiàn)形式就是pom.xml哄褒。前面提到的工程的坐標(biāo),用到的插件煌张,依賴的包等都是用來描述Maven工程的呐赡,這些信息就是模型的一部分,所以我們定義在pom.xml文件中骏融。除了上面提到的模型信息外链嘀,下面在介紹幾個(gè)模型的抽象萌狂。

6.1 Properties

可以把properties想象為POM的自定義占位符,用來替換POM中的硬編碼怀泊。下面的例子使用properties中自定義的標(biāo)簽spring.version替換spring-webmvc的版本號(hào)茫藏。

<properties>
    <spring.version>4.3.22.RELEASE</spring.version>
</properties>

<dependenies>
    <dependeny>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependeny>
</dependenies>

6.2 更多參考

Apache官網(wǎng)上列出POM模型的更多參考。連接地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末霹琼,一起剝皮案震驚了整個(gè)濱河市务傲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌枣申,老刑警劉巖售葡,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異糯而,居然都是意外死亡天通,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門熄驼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來像寒,“玉大人,你說我怎么就攤上這事瓜贾∨祷觯” “怎么了?”我有些...
    開封第一講書人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵祭芦,是天一觀的道長(zhǎng)筷笨。 經(jīng)常有香客問我,道長(zhǎng)龟劲,這世上最難降的妖魔是什么胃夏? 我笑而不...
    開封第一講書人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮昌跌,結(jié)果婚禮上仰禀,老公的妹妹穿的比我還像新娘。我一直安慰自己蚕愤,他們只是感情好答恶,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著萍诱,像睡著了一般悬嗓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上裕坊,一...
    開封第一講書人閱讀 50,021評(píng)論 1 291
  • 那天包竹,我揣著相機(jī)與錄音,去河邊找鬼。 笑死周瞎,一個(gè)胖子當(dāng)著我的面吹牛悟狱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播堰氓,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼挤渐,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了双絮?” 一聲冷哼從身側(cè)響起浴麻,我...
    開封第一講書人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎囤攀,沒想到半個(gè)月后软免,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡焚挠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年膏萧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝌衔。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡榛泛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出噩斟,到底是詐尸還是另有隱情曹锨,我是刑警寧澤,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布剃允,位于F島的核電站沛简,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏斥废。R本人自食惡果不足惜椒楣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望牡肉。 院中可真熱鬧捧灰,春花似錦、人聲如沸荚板。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽跪另。三九已至,卻和暖如春煤搜,著一層夾襖步出監(jiān)牢的瞬間免绿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工擦盾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嘲驾,地道東北人淌哟。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像辽故,于是被迫代替她去往敵國(guó)和親徒仓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 參考資料: http://ifeve.com/maven-1/ http://ifeve.com/maven-2/...
    這個(gè)該叫什么呢閱讀 526評(píng)論 0 1
  • |-1-更新內(nèi)容[6.從倉(cāng)庫(kù)解析依賴的機(jī)制(重要)] 1Maven倉(cāng)庫(kù)作用 倉(cāng)庫(kù)用來存儲(chǔ)所有項(xiàng)目使用到構(gòu)件誊垢,在ma...
    zlcook閱讀 6,038評(píng)論 0 25
  • Maven的基本了解 什么是Maven掉弛? Maven就是Apache下的一個(gè)開源項(xiàng)目。它是用純java開發(fā)的喂走。是一...
    Bcome閱讀 2,793評(píng)論 0 7
  • Maven是一個(gè)強(qiáng)大的Java項(xiàng)目構(gòu)建工具 什么是構(gòu)建工具殃饿? 構(gòu)建工具是將軟件項(xiàng)目構(gòu)建相關(guān)的過程自動(dòng)化的工具。構(gòu)建...
    pure_joy閱讀 777評(píng)論 0 0
  • 文/花隱 W打開手機(jī)app store 下載了一個(gè)新浪微博 然后登陸時(shí)雖然微博自動(dòng)登錄了 但是她很快速的點(diǎn)擊右上角...
    Fortune花隱閱讀 565評(píng)論 1 2