走進JavaWeb技術世界12:從手動編譯打包到項目構建工具Maven


小李的Build之路(上)

轉自: 劉欣 碼農翻身 2016-07-10

  • 摘要:手工Build的煩惱要不是爲了和女朋友留在一個城市,小李肯定去北上廣奮鬥去了。現在他只能留在這個2.5線城市,進入這家軟件開發公司,7,8個人,10來條槍,是個典型的軟件小作坊。上班第一天,CTO兼架構師兼項目經理兼開發組長老張把小李叫去,諄諄教導說:“小李啊,我看了你的簡歷,我對你在公司的發展還是挺看好的,不過作爲新人,你對新業務還不熟悉,沒法開發核心系統,這段時間,你要一邊學習,一邊幫着項目做個很重要的工作:Build“小李心說你還給我拽英語啊,雖然心裏這麼想,小李還是不

  • 手工Build的煩惱

    要不是爲了和女朋友留在一個城市,小李肯定去北上廣奮鬥去了。

     

    現在他只能留在這個2.5線城市,進入這家軟件開發公司,7,8個人,10來條槍,是個典型的軟件小作坊。

     

    上班第一天,CTO兼架構師兼項目經理兼開發組長老張把小李叫去,諄諄教導說:

     

    “小李啊,我看了你的簡歷,我對你在公司的發展還是挺看好的,不過作爲新人,你對新業務還不熟悉,沒法開發核心系統,這段時間,你要一邊學習,一邊幫着項目做個很重要的工作:Build“

     

    小李心說你還給我拽英語啊, 雖然心裏這麼想, 小李還是不動聲色,面帶微笑的問:

     

    “這Build是什麼東西?”

     

    老張說:“我非常忙, 沒時間給你解釋,這兒有個文檔,你看看就知道了”

     

    說着,老張甩給了他幾張紙 ,補充到: “有問題問小王, 他比你早來一個月,做Build已經很熟了”

     

    小李仔細看了一遍,上面寫着:

     

    XXX公司Build 流程 (測試環境)

    (1) 設置Eclipse 工作區, 編碼爲UTF-8, java 編譯級別爲JDK 1.7

     

    (2) 從SVN下載最新源代碼到Eclipse工作區

     

    (3) 確保Eclispe工作區沒有編譯錯誤

     

    (4) 手工修改下面 20個 配置文件

    database.properties

    cache.properties

    user.properties

    。。。。。。

    (5) 把Eclipse中的Web項目導出成War 包

    小王還特別在這裏用紅色的筆加了標註: Web項目所依賴的其他java項目也會被自動包含到War包的 WEB-INF/lib目錄下

     

    (6) 上傳到測試服務器,安裝

     

    (7) 做冒煙測試

     

    小李笑了:這不就是一個編譯,打包,部署,測試的流程嗎? 還Build !

     

    正在這時,開發骨幹小樑叫小李了:“小李, 我改了幾個Bug,馬上要測試,趕緊給我做一個測試環境的Build”

     

    小李不敢怠慢,立刻按照文檔做了一遍,花了將近半個小時才折騰完。

     

    可是到了最後一步,做冒煙測試的時候, 系統卻啓動不了了 !

     

    小李查了好久才發現,原來測試環境的JDK是1.6 , 但是Build文檔上寫的是1.7 當然跑不起來了。

     

    小李暗暗的罵前任小王: 你小子肯定知道這裏有個坑, 怎麼不在文檔上標註出來?

     

    趕緊做個新的Build 放到測試環境, 這次冒煙測試順利通過了。

     

    剛鬆了口氣, 測試小趙就叫了起來: “小樑, 你那個Bug 沒有修復啊”

     

    開發骨幹小樑本能的反應到: “這不可能! 我的代碼本地都測試過了, 代碼也提交了“

     

    小樑接着把矛頭就指向小李: “哎對了小李,你的Build是不是又搞錯了。”

     

    小李心頭一驚 , 趕緊去查,果然,在第4步,手工修改配置文件的時候把數據庫改錯了 ,指向了開發庫,而不是測試庫。

     

    趕緊改吧, 原來做Build的小王也跑過來湊熱鬧, 在前Build專員小王,開發小樑和測試小趙三雙眼睛的嚴厲注目下, 小李頭上都要冒汗了。

     

    還好,第三次終於成功了。 所有的測試都順利通過。

     

    (實際上,小李在緊張的忙碌中也忘了去更新那個文檔,把JDK 改成1.6)

     

    就這樣過了一週, 小李每天都得戰戰兢兢的做四五個Build, 雖然做的越來越熟,出錯越來越少, 但是每天還是佔用了不少時間。

     

    大好年華就要在Build中蹉跎了嗎, 堅決不行。

    自動化Build

    小李決定把這個手工的、費事的、容易出錯的Build給自動化起來, 將來誰要是做測試環境的Build,只要運行一個命令即可。

     

    用什麼語言來實現呢? 當然是Java大法好 ! 小李在大學修煉了那麼久,自認爲對OO,設計模式已經爐火純青了, 現在終於有了用武之地。

     

    小李白天工作, 晚上回到住處就開發這個自動化的Build, 每天干到12點才罷休。

     

    但是小李不覺得累, 每天都戀戀不捨的去上牀睡覺, 因爲創造一個新工具,造福大家的想法一直激勵着自己,有時候甚至覺得很快樂。

     

    一個月後, 自動化工具新鮮出爐, 這其實是一套Java 的API, 小李把它稱爲BuildTool V1.0 專門用於下載源碼,編譯,打包,部署,測試。

    例如,如果你想編譯java 代碼, 可以這麼寫:

    小李的 Build 之路 (上)_Java

    小李對於FileSet這個抽象很得意, 它能代表一個文件集合, 既可以是java 源文件路徑, 也可以是 classpath 的路徑。

     

    其他的API像下載源碼, 打包,部署,測試也是類似。

     

    現在小李真的只需要運行一個命令,就可以爲測試環境生成一個build :

    java BuildTool test

     

    工作量一下子少了好多, 並且機器運行,基本上不會出錯。

     

    小李因爲這個自動化的BuildTool, 獲得的公司的嘉獎,還漲了一點工資。

     

    對小李來說,這都不是最重要的, 最重要的通過設計和實現這個BuildTool, 自己的能力有了很大的提升。

     

    自己已經 不僅僅是一個只會用SSH框架的一個HTML填空人員了!

    碼農翻身評: 大部分人只會抱怨項目很無趣,沒有挑戰, 遇到問題也只會安於現狀,

    少數人會發現工作中的“痛點”問題,並且真正動手解決它, 給公司帶來了價值, 這是提高自己, 讓自己和別人區分開來的重要方法。

    JAVA vs XML

    今年的形勢很好,公司業務發展的不錯,招了一批新人,一下子接了3,4 個新項目, 小李主動請纓,替這些項目建立一個自動化的Build 。

     

    但是小李很快就發現了問題, 直接用Java語言來編寫,功能雖然能實現, 但是看起來就太繁瑣了。

    自己寫的代碼過幾天看也得思考一下才能明白。

    是自己的BuildTool API設計的不好嗎? 那可是精心設計的啊。

     

    仔細思考了兩天,小李終於意識到了問題所在: 不是自己設計的不好, 是Java 語言太“低級”了 !

     

    自動化Build要描述的其實是任務,是業務層面的東西。

     

    而用java 是個什麼都能幹的通用語言, 用它來寫肯定引入了太多的細節,導致了閱讀和編寫的難度!

     

    小李想:能不能開發一套新的,專門爲自動化Build 所使用的語言呢?

    (碼農翻身注: 這其實就是所謂的領域特定語言(Domain Specific Language , 簡稱 DSL ))

     

    但是開發一套新語言那成本可就有點高了, 有點得不償失。

     

    小李百思不得其解, 直到有一天聽到小樑和項目經理在討論hibernate 的配置文件,突然想到 像spring , hibernate 都是用XML來描述系統的。

     

    “那我的BuildTool也完全可以用XML來描述啊”小李趕緊把那個編譯java 的程序用XML描述了一下:

    小李的 Build 之路 (上)_Java

    果然是清爽多了! 和原來的Java程序比起來, 這段XML幾乎就是自解釋的 !

     

    XML可擴展性極強, 可以任意自定義標籤諸如<javac> <srcDir> <classpath> 用它來描述Build的邏輯。

     

    但是唯一不爽的地方就是: XML 無法像 Java程序那樣運行, 只是純文本而已。

     

    不過這也無妨,只要用Java寫一個解析器,用來解析這些XML文件然後在Java中執行就可以了。有了BuildTool V1.0作爲基礎, 寫一個解析器不是什麼難事, 很快 BuildTool V2.0 就新鮮出爐了。

     

    小李不再幫其他項目組去寫Build 程序,因爲用XML描述以後,大家很快就能學會, 並且樂在其中。

    CTO老張看到這個工具,大爲讚賞, 它給小李說: “別叫什麼Build Tool, 太俗, 別人聽了一點感覺都沒有, 我給你起個名,叫 ANT ”

     

    "ANT? " 小李似乎看到很多小螞蟻在不辭勞苦幫着做Build, 心裏暗暗佩服老張: 這個名字起的太好了, 薑還是老的辣啊。

小李的Build之路(下)

轉自: 劉欣 碼農翻身 2016-07-12

前言: 接上一篇《小李的Build之路(上)

 

小李發明的ANT確實是好用, 現在不僅僅是小李的公司, 連其他公司的朋友聽說了,也拿去使用, 交口稱讚。

 

只是小李發現了一點奇怪的現象,每個人在開始寫新項目的Ant build文件之前, 都會找到自己說:

“小李, 把你那個build.xml 文件發我一份吧, 讓我參考下。”

 

小李的那一份build.xml其實是自己項目的第一個ant 腳本, 爲啥大家都要把它

Copy走呢?   剛開始的時候小李以爲大家不會寫,要按照自己的模板照葫蘆畫瓢。 

 

偶然有一次,小李看到了別人項目的Ant build腳本, 不由得大吃一驚, 這簡直和自己原始的build.xml如出一轍。 

 

小李趕緊把公司內所有項目的Ant腳本都要過來,仔細觀察了一下, 很快就發現了這些腳本中蘊藏着一些共同的“模式”,這些模式主要體現在Build的步驟上:

 

1. 從版本控制系統下載代碼

2. 編譯java 文件,形成jar包

3. 運行單元測試

4. 生成代碼覆蓋度報告和測試報告

4. 打包形成war 文件

5. 上傳到測試服務器上,進行安裝

 

其實這也難怪,實際的Build不就是這樣的嘛。 但是中間也有不同之處:

 

(1) 路徑不同,例如

java 源文件 下載下來以後放的位置不同,五花八門

編譯成的java class 放置的位置不同

測試報告放置不同

war包生成後放置的路徑不同

。。。

 

(2)  項目依賴不同,例如

各個項目依賴的第三方jar包可能是不一樣的

各個項目都有一個Web子項目,它依賴於其他java 項目,所以在build的時候,要先build這些java 項目才行

例如下圖中的OnlineShop,這是個Web項目, 它依賴於ApplicationConfg, LoggingFramework, OnlineShopApi這三個子項目。

 

項目依賴這個沒辦法, 畢竟是各個項目的業務所要求的,小李沒有辦法改變。

 

但是那些不同的路徑真的是必要的嗎?   能不能讓大家的路徑都保持一致呢 ? 

 

一個新的主意像閃電一樣劃過黑暗的夜空: 

確實可以保持一致, 但是大家都要遵循一定的約定

如果大家都這麼做,小李就可以增強一下Ant,只要運行ant  complie , 就會自動的去src/main/java 找到源文件進行編譯, 只要運行ant test,        就會自動去src/test/java 找到測試用例, 編譯並運行。

 

換句話說,只要遵循目錄的約定, 大家就不用費心費力的指定各種路徑了, 一切在背後由工具自動搞定, 這樣的話Build腳本就可以極大的簡化了,只需要寥寥幾行即可。

 

這只是一個java項目,要是多個java項目,有依賴關係,像上面提到的 OnlineShop 依賴OnlineShopAPI, AppplicationConfig, LoggingFramework , 該怎麼處理?

 

這也不難, 小李想,首先每個java項目都得遵守上述約定,其次需要定義項目之間的依賴關係, 也可以用XML描述出來。

 

每個java項目都需要有個叫pom.xml的文件, 例如OnlineShop這個項目的pom如下:

 

這樣以來工具就能自動找到被依賴的項目, 然後去編譯打包它了。

 

此外,各個java項目之間也需要按約定來組織目錄,例如:

+- pom.xml

+- online-shop-web

| +- pom.xml

| +- src

|   +- main

|     +- webapp

+- online-shop-api

| +- pom.xml

| +- src

|   +- main

|     +- java

+- logging-framework

| +- pom.xml

| +- src

|   +- main

|     +- java

+- app-config

| +- pom.xml

| +- src

|   +- main

|     +- java

 

如果擴展一下, 把第三方的jar 文件例如JUnit 也可以給用這種方式來描述:

想到這一層,小李不禁激動起來,因爲第三方的jar 管理一直是一個令人頭疼的問題,最早的時候大家都是手工的Copy來Copy去, 由於版本不同導致的錯誤特別難於發現。

 

每個人在建立自己Eclipse workspace的時候, 得拿到所有依賴的jar包, 並且在項目上設置好, 可是非常的費勁啊。 

 

如果利用這種聲明的辦法, 每個人豈不卸下了一個巨大的包袱 ? 

 

當然公司需要建立一個公用的第三方jar 文件版本庫, 把公司最常用的第三方jar包都放進去, 工具在分析項目的配置文件pom.xml的時候,就可以去公司的版本庫裏去讀取並且下載到本地。

 

將來有新人進入公司, 只要給他一個pom.xml , 用Eclipse導入,就能輕鬆的把一個可以直接運行的workspace建立起來, 再也不需要設置那些煩心的jar了。

 

如果將來在網絡上建立公開的軟件版本庫, 任何人都可以從那裏去下載各種軟件包,那受惠的可不僅僅是自己公司了, 而是所有人,真是一個激動人心的場景啊。

 

不過還是從自己公司開始吧, 小李冷靜下來分析了一下: 讓所有的項目組都使用約定的目錄,並且建立一個公司級別的軟件庫,自己可是沒有這樣的權限啊, 小李去找CTO老張求助。

 

老張不愧是老江湖, 聽了幾分鐘小李的介紹,馬上就明白了, 並且把這個想法提升了一個高度:

 

“你這叫約定重於配置, 知道不?  從Ruby on Rails 開始,這個詞開始流行了, 大家現在都很忙, Ant build腳本用的也沒問題,先不改了”

 

小李還不死心: “可是這麼做的話對以後的新項目大有好處啊,不用Copy 繁瑣的build腳本了, 也不用費心的折騰workspace了”

 

“那也不能現在改,項目進度最重要,大家都沒時間, 這樣吧,等大家項目閒下來再改動如何? ” 老張妥協了一下。

 

可是在公司基本上就不會有空閒的時間, 一個個新需求壓的大家透不過氣來,偶爾有空閒時間,大家也都犯懶了, 總是想休息。 

 

此外慣性的力量是驚人的,大家都願意待在舒適區裏, 不願意變化,  雖然也看到了新工具的好處, 大家都懶得換新的。 

 

時間過的很快,一年過去了, 小李看着自己辛辛苦苦加班寫出來的Ant 2.0 ,  還是無人採用, 很是傷心。 

 

經過公司的允許, 小李決定把這個工具開源, 爲了和Ant區分開來, 特地起了個新的名稱: Maven。

 

Maven 迅速被大家用了起來,除了小李的公司。

 

又過了半年, 小李跳槽了。 

 

(完)

 

(完)

Maven 三十分鐘入門

閱讀 1164

收藏 95

2017-05-08

原文鏈接:sadwxqezc.github.io

Maven

Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model(POM), Maven can manage a project’s build, reporting and documentation from a central piece of information.

參考文檔:Maven Documentation

Maven概述

一個基本的Pom文件

<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.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Pom文件是面向工程的一個管理模型,全稱是Project Object Model。這個Pom文件中包含的基本內容有:

  1. project pom文件的頂層元素

  2. modelVersion Pom對象模型的版本

  3. groupId 是創建這個項目的組織或部門的唯一標誌,比如說org.apache.maven.plugins就是所有Maven plugins的groupId

  4. artifactId 是這個項目生成結果的唯一標誌,Maven生成結果的命名模式爲<artifactId>-<version>.<extension>,比如說my app-1.0.jar

  5. packaging 這個參數表明了項目生成結果的打包模式,比如JAR,WAR,EAR等,同時這個參數還表明了build過程採用的特定生命週期

  6. version 這個參數表明了項目生成結果的版本,在version裏經常會看到SNAPSHOT標誌,它表明了項目處於開發階段。

  7. name 這個參數代表項目的展示名字,通常作用在Maven生成的文檔中

  8. url 這個參數代表哪裏可以找到該項目,通常作用在Maven生成的文檔中

  9. description 這個參數描述了項目的基本信息,通常作用在Maven生成的文檔中

Maven項目的基本結構

my-app
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

上面是一個Maven項目的基本結構,項目的相關資源位於${basedir}/src/main/java中,而測試的資源位於${basedir}/src/test/java中,而pom文件位於pom.xml中。

Maven的執行

1. mvn compile

執行mvn compile,編譯的結果會默認放在${basedir}/target/classes目錄下。

2. mvn test

執行mvn test,會執行${basedir}/src/test/java中的單元測試。如果只想編譯測試代碼而不執行,則執行mvn test-compile

3. mvn package

執行mvn package會對項目進行打包,假如當前在pom中的packaging設定爲jar,那麼執行該命令後會在${basedir}/target目錄下生成對應的jar包。

4. mvn install

如果想把mvn package生成的Jar文件安裝在本地庫中以讓其它項目引用,則可以執行mvn install命令,將生成的jar包放在${user.home}/.m2/repository中。

Plugins

Plugins用來定製Maven項目的編譯過程,假如要配置Java Compiler允許JDK 5.0的資源,那麼只需要在Pom中增加如下內容:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.3</version>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>
  </plugins>
</build>

<configuration>中的配置會應用在對應Plugin的所有Goal。

資源文件打包

${basedir}/src/main/resources目錄下的所有文件都會被打包到Jar文件中,比如如下一個文件結構:

my-app
|-- pom.xml
`-- src
    |-- main
    |   |-- java
    |   |   `-- com
    |   |       `-- mycompany
    |   |           `-- app
    |   |               `-- App.java
    |   `-- resources
    |       `-- META-INF
    |           `-- application.properties
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

該項目打包成Jar文件後的內部組織結構爲:

|-- META-INF
|   |-- MANIFEST.MF
|   |-- application.properties
|   `-- maven
|       `-- com.mycompany.app
|           `-- my-app
|               |-- pom.properties
|               `-- pom.xml
`-- com
    `-- mycompany
        `-- app
            `-- App.class

文件過濾

Maven支持文件過濾的功能,可以在build時候爲文件提供變量賦值,比如說上面的application.properties文件中有如下定義:

# application.properties
application.name=${project.name}
application.version=${project.version}

那麼需要在pom文件中做如下的定義:

<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.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>
</project>

執行mvn process-resources命令後,在target/classes下找到application.properties可以看到如下結果:

# application.properties
application.name=Maven Quick Start Archetype
application.version=1.0-SNAPSHOT

可見其中形如${<property name>}的變量已經被替換成了對應的值,如果要引入其它文件中定義的屬性,只需要在pom文件中定義<filters>,比如:

  <build>
    <filters>
      <filter>src/main/filters/filter.properties</filter>
    </filters>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>

那麼Maven會先讀出filter.properties中的屬性,然後把這些屬性注入對應的resources中。

Dependencies

<dependencies>標籤下列出了所有的外部依賴,比如下面的Pom文件添加了Junit的依賴:

<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.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

<dependency><scope>標籤的值可以爲compile,test和runtime,當Maven編譯項目時,它首先會在${user.home}/.m2/repository這個本地庫目錄下尋找所需的依賴,如果沒有會去遠程的庫上尋找,並將其下載到本地庫中,默認的遠程庫地址爲 http://repo.maven.apache.org/maven2/

包的發佈

當需要發佈一個包的遠程倉庫時,需要配置庫的地址和相應的權限,一個範例如下:

<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.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.codehaus.plexus</groupId>
      <artifactId>plexus-utils</artifactId>
      <version>1.0.4</version>
    </dependency>
  </dependencies>

  <build>
    <filters>
      <filter>src/main/filters/filters.properties</filter>
    </filters>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>
  <!--
   |
   |
   |
   -->
  <distributionManagement>
    <repository>
      <id>mycompany-repository</id>
      <name>MyCompany Repository</name>
      <url>scp://repository.mycompany.com/repository/maven2</url>
    </repository>
  </distributionManagement>
</project>

它所需要的權限配置在settings.xml中:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      http://maven.apache.org/xsd/settings-1.0.0.xsd">
  ...
  <servers>
    <server>
      <id>mycompany-repository</id>
      <username>jvanzyl</username>
      <!-- Default value is ~/.ssh/id_dsa -->
      <privateKey>/path/to/identity</privateKey> (default is ~/.ssh/id_dsa)
      <passphrase>my_key_passphrase</passphrase>
    </server>
  </servers>
  ...
</settings>

多Modules管理

Maven很好的支持了多個Modules的管理,假如一個Maven項目結構如下:

+- pom.xml
+- my-app
| +- pom.xml
| +- src
|   +- main
|     +- java
+- my-webapp
| +- pom.xml
| +- src
|   +- main
|     +- webapp

對於根目錄下的pom文件,內容如下:

<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.mycompany.app</groupId>
  <artifactId>app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>

  <modules>
    <module>my-app</module>
    <module>my-webapp</module>
  </modules>
</project>

其中的<modules>定義了其管理的兩個子modules。

假如my-webapp需要依賴my-app包,那麼在my-webapp/pom.xml中增加:

  ...
  <dependencies>
    <dependency>
      <groupId>com.mycompany.app</groupId>
      <artifactId>my-app</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    ...
  </dependencies>

然後在my-app和my-webapp的pom文件中都增加parent配置:

<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">
  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>app</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  ...

然後在最頂層目錄下執行mvn clean install,會創建my-webapp/target/my-webapp.war,其中包含:

$ jar tvf my-webapp/target/my-webapp-1.0-SNAPSHOT.war
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/
 222 Fri Jun 24 10:59:54 EST 2005 META-INF/MANIFEST.MF
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/
3239 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.xml
   0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/
 215 Fri Jun 24 10:59:56 EST 2005 WEB-INF/web.xml
 123 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.properties
  52 Fri Jun 24 10:59:56 EST 2005 index.jsp
   0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/
2713 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/my-app-1.0-SNAPSHOT.jar

可見my-app-1.0-SNAPSHOT.jar已經被放到了WEB-INF/lib目錄下。



一位阿里 Java 工程師的技術小站。作者黃小斜,專注 Java 相關技術:SSM、SpringBoot、MySQL、分佈式、中間件、集羣、Linux、網絡、多線程,偶爾講點Docker、ELK,同時也分享技術乾貨和學習經驗,致力於Java全棧開發!(關注公衆號後回覆”Java“即可領取 Java基礎、進階、項目和架構師等免費學習資料,更有數據庫、分佈式、微服務等熱門技術學習視頻,內容豐富,兼顧原理和實踐,另外也將贈送作者原創的Java學習指南、Java程序員面試指南等乾貨資源)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章