十分鐘解惑柜裸,讓你真正用好MAVEN

我們?nèi)粘9ぷ髦薪?jīng)常使用到maven擂错,基本操作大家都會味滞,但是涉及到父子pom繼承和多模塊的時候,很多時候使用的就會很混亂钮呀。

本篇文章主要針對maven的父子pom繼承和多模塊展開一些討論剑鞍,默認(rèn)讀者以使用過maven(可參考:https://www.ibofine.com/mavenbook/index.html

1 MAVEN的關(guān)于依賴的基本配置

1.1 坐標(biāo)(定位三要素)

<project>
    <groupId>xxx.xxxxx.xxxx</groupId> <!-- 公司業(yè)務(wù) -->
    <artifactId>xxx-xxxx</artifactId> <!-- 項目 -->
    <version>1.0.0</version> <!-- 版本 -->

    <!-- ....其他配置 -->
</project>

1.2 定義屬性

<project>
    <properties>
        <custom-data>hello</custom-data> <!-- 自定義一個屬性,在pom及子pom中使用${} 的形式使用 -->
        <lombok-version>1.18.10</lombok-version> <!-- 定義lombok的版本號 -->
    </properties>
</project>

1.3 申明依賴

<project>
    <dependencyManagement>
        <dependencies>
            <!-- 定義好可能使用的包和版本 -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok-version}</version> <!-- 版本統(tǒng)一放在屬性里面管理爽醋,方便看蚁署,此處引用 -->
            </dependency>
        
            <!-- .....其他包 -->
        </dependencies>
    </dependencyManagement>
</project>

1.4 使用依賴

<project>
    <dependencies>
        <!-- 實際使用的包,dependencyManagement 定義過版本蚂四,實際使用的時候不需要寫版本 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    
        <!-- .....其他包 -->
    </dependencies>
</project>

1.5 排除依賴

<project>
    <properties>
        <custom-data>hello</custom-data> <!-- 自定義一個屬性光戈,在pom及子pom中使用${} 的形式使用 -->
        <lombok-version>1.18.10</lombok-version> <!-- 定義lombok的版本號 -->
        <spring.version>5.2.4.RELEASE</spring.version> 
    </properties>

    <dependencyManagement>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
            <exclusions>
                <exclusion> <!-- 排除日志包 commons-logging ,也可以選擇在使用引用的時候排除 -->
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencyManagement>
</project>

注意: 排除依賴存在一些未知的風(fēng)險。比如 A-->B, B-->C遂赠, 當(dāng)B的某個實現(xiàn)需要C久妆, 而B的這實現(xiàn)會在A中運(yùn)行的時候,排除了C就可能出錯跷睦。

2 MAVEN依賴特性

2.1 maven的依賴存在傳遞性

如下:

A --> B , B-->C 則 A -- > B --> C

A 依賴了B包 筷弦, B中依賴C包 ,則 A如果自動會導(dǎo)入C ( 這個原因也是為什會有 排除依賴的存在,有時候A只想依賴B烂琴,而不想要C的時候爹殊。)

2.2 依賴順序原則

依賴的順序決定了最終使用的是哪個jar包,maven在解析依賴的時候的順序是奸绷。先按最短路徑梗夸,再按申明順序

  • 最短路徑優(yōu)先
    如 a--> b --> c1.1.0 , a-->d --> e -->c1.2.0 則最終a中用的 c1.1.0

  • 申明順序優(yōu)先
    當(dāng)路徑相同的時候,不能判斷使用哪個号醉,這時候就是按照申明的順序 反症,如 a-->b-->c1.1.0 a-->d-->c1.2.0 此時,如果路徑c是一樣的扣癣,如果b的申明在d的前面惰帽,
    在使用的是 c1.1.0, 反之則為 c1.2.0

3 MAVEN繼承特性(父子pom)

在pom文件中定義parent節(jié)點之后,子pom就可以繼承父pom中的依賴和屬性父虑。

通常使用這個特性该酗,在父pom中統(tǒng)一一些公共的東西,如jar版本士嚎,定義的一些屬性等呜魄。主要就是抽離,統(tǒng)一管理莱衩。

<project>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository , 這時候 spring-boot-starter-parent 中定義的屬性和依賴都可以在當(dāng)前pom中使用 -->
    </parent>

    <groupId>com.fun</groupId>
    <artifactId>learn</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>learn</name>
    <description>Demo project for Spring Boot</description>
</project>

4 MAVEN聚合特性(module)

module可以看做是項目結(jié)構(gòu)的描述爵嗅,通過<modules><module>...</module></modules> 來定義,可以一起來打包的一個整體笨蚁。

<project>
    <groupId>com.fun</groupId>
    <artifactId>learn</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>learn</name>
    <description>Demo project for Spring Boot</description>
    
    <modules>
        <module>learn-api</module>
        <module>learn-server</module>
    </modules>
</project>

<!-- 
上面配置的項目結(jié)構(gòu)
learn
   |-learn-api
   |-learn-server
-->

5 MAVEN繼承與聚合的區(qū)別

繼承和聚合沒有絕對要求的對應(yīng)關(guān)系睹晒,他們目的上是不同。

  • 繼承 講究的是提煉統(tǒng)一公共的部分括细,子項目都使用伪很,統(tǒng)一管理公共部分。(使用時候奋单,可以單獨定義一個父pom給所有的項目使用锉试,統(tǒng)一項目中的jar包)

  • 聚合 更像是定義項目的結(jié)構(gòu),哪些作為一個整理览濒。

6 MAVEN最佳實踐

6.1 實踐場景

假設(shè)有下面一個實例呆盖,一個系統(tǒng)(fun-mall)有 用戶服務(wù)(user)、訂單服務(wù)(order)贷笛、支付服務(wù)(pay)应又、商品服務(wù)(product), 他們之間通過dubbo調(diào)用乏苦。那么我們的使用maven可以統(tǒng)一成如下結(jié)構(gòu)

xxx-api 提供dubbo調(diào)用的一些接口定義丁频,**建議盡量少的依賴第三方的包。理論上他只是定義接口的和數(shù)據(jù)模型的。不然席里,當(dāng)別人引用你的時候,可能出現(xiàn)第三方包的沖突拢驾,需要排除依賴**
xxx-server 啟動jvm的進(jìn)程

fun-mall
    |-- user
        |-- user-api
        |-- user-server
    |-- order
        |-- order-api
        |-- order-server
    |-- pay
        |-- pay-api
        |-- pay-server
    |-- product
        |-- product-api
        |-- product-server

針對上面的接口奖磁,我們創(chuàng)建項目的時候有兩種比較合理的方式

6.2 實現(xiàn)方式1

  1. 創(chuàng)建一個項目 fun-mall 一個git倉庫地址,fun-mall下面包含四個module繁疤, 每個module下面有包含xxx-api,xxx-server 兩個module咖为, 所有模塊的父pom都使用fun-mall(繼承和聚合的區(qū)別)
fun-mall
    |-- user
        |-- user-api
            |-- pom.xml
        |-- user-server
            |-- pom.xml
        |-- pom.xml
    |-- order
        |-- order-api
            |-- pom.xml
        |-- order-server
            |-- pom.xml
        |-- pom.xml
    |-- pay
        |-- pay-api
            |-- pom.xml
        |-- pay-server
            |-- pom.xml
        |-- pom.xml
    |-- product
        |-- product-api
        |-- product-server
        |-- pom.xml
    |-- pom.xml

具體配置

fun-mall的 pom.xml

<project>
    <groupId>com.fun</groupId>
    <artifactId>fun-mall</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>fun-mall</name>
    <description>fun mall</description>
    <packaging>pom</packaging> <!-- 注意是pom -->
    
    <modules>
        <module>user</module>
        <module>order</module>
        <module>pay</module>
        <module>product</module>
    </modules>

    <properties>
        <!-- 一些通用的屬性 -->
    </properties>
    
    <dependencyManagement>
        <dependency>
            <!-- 依賴的jar和版本申明 -->
        </dependency>
    </dependencyManagement>
    
    <!-- 其他配置 -->
</project>

user 的pom.xml

<project>
    <parent>
        <groupId>com.fun</groupId>
        <artifactId>fun-mall</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>user</artifactId>
    <description>user module</description>
    <packaging>pom</packaging> <!-- 注意是pom, 另外groupId和version繼承父類 -->
    
    <modules>
        <module>user-api</module>
        <module>order-server</module>
    </modules>

    <dependencies>
        <dependency>
            <!-- 實際依賴的jar和版本 -->
        </dependency>
    </dependencies>
    
    <!-- 其他配置 -->
</project>

user-api 的pom.xml

<project>
    <parent>
        <groupId>com.fun</groupId>
        <artifactId>fun-mall</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>user-api</artifactId>
    <description>user server api define </description>
    <packaging>jar</packaging> <!-- 打包成jar提供出去給別的服務(wù)使用,另外groupId和version繼承父類稠腊,也可自己指定新的 -->

    <dependencies>
        <dependency>
            <!-- 實際依賴的jar和版本 -->
        </dependency>
    </dependencies>
    
    <!-- 其他配置 -->
</project>

user-server的pom.xml

<project>
    <parent>
        <groupId>com.fun</groupId>
        <artifactId>fun-mall</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>user-server</artifactId>
    <description>user server impl</description>
    <packaging>jar</packaging> <!-- 打包成可運(yùn)行的jar或者war躁染,或者zip等格式 。另外groupId和version繼承父類架忌,也可自己指定新的-->

    <dependencies>
        <dependency>
            <!-- 實際依賴的jar和版本 -->
        </dependency>
    </dependencies>
    
    <!-- 添加打包可運(yùn)行的jar或者war或者zip的配置 -->

    <!-- 其他配置 -->
</project>

order吞彤、pay、product的配置叹放,同user模塊類似即可饰恕。

6.3 實現(xiàn)方式2

  1. 創(chuàng)建一個fun-mall 做個父項目,沒有模塊井仰。 然后分別創(chuàng)建四個 項目 user埋嵌、order、pay俱恶、product 繼承這個fun-mall 拱為5個git地址雹嗦,所有項目的parent都是 fun-mall(繼承和聚合的區(qū)別)
fun-mall
    |-- pom.xml

--------

|-- user
    |-- user-api
        |-- pom.xml
    |-- user-server
        |-- pom.xml
    |-- pom.xml

--------

|-- order
    |-- order-api
        |-- pom.xml
    |-- order-server
        |-- pom.xml
    |-- pom.xml

--------

|-- pay
    |-- pay-api
        |-- pom.xml
    |-- pay-server
        |-- pom.xml
    |-- pom.xml

--------

|-- product
    |-- product-api
    |-- product-server
    |-- pom.xml

這種方式的pom和上面在一個工程里面的方式是沒有區(qū)別的,只是代碼放在不同的倉庫地址里面而已合是。

考慮到不同模塊迭代速度不同了罪,每個服務(wù)有自己的代碼和分支進(jìn)行開發(fā),相比上面在整個一個git而言端仰,更加靈活捶惜,不用對其他的服務(wù)產(chǎn)生分支。

其次荔烧,如果涉及到不同服務(wù)給不同團(tuán)隊開發(fā)吱七,或者不同服務(wù)不需要看別人的實現(xiàn)的。只關(guān)心自己鹤竭,則分開倉庫很好的滿足了

7 MAVEN deploy時父pom的問題

我們在deploy jar的時候踊餐,經(jīng)常遇到一些因為父pom沒有推導(dǎo)致推包失敗的情況。所有一般推包看分為兩種情況來處理

7.1 子pom未使用父pom的變量

這種情況下

  • 方式1:因為子pom沒有使用父pom的變量臀稚,可能考慮單獨deploy, 注釋掉<parent>, 然后確保自己有artfactId和version 吝岭,直接deploy.

  • 方式2:先推一下父pom,在推子模塊。如果pom有很多子模塊(fun-mall的第一種)窜管,可考慮只推父pom(mvn clean deploy -N)散劫,
    不要推子模塊(所有的模塊都推,連實現(xiàn)server可能都推了幕帆,沒必要)获搏,然后再推需要的jar(如,user-spi失乾,)

7.2 子pom有使用父pom的變量

這種情況下, 因為使用父模塊的變量常熙,不能使用注釋parent(不然不識別),所有只能先推一下父pom, 再推當(dāng)前jar, 如上面的方式二

7.3 記錄

  • 跳過Assembly:clean deploy -DskipAssembly=true
  • 只推父pom: mvn clean package deploy -Dmaven.test.skip=true -Drepository:snapshots -N
  • 分析maven的依賴樹: mvn dependency:tree >text.txt
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碱茁,一起剝皮案震驚了整個濱河市裸卫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纽竣,老刑警劉巖墓贿,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異退个,居然都是意外死亡募壕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門语盈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舱馅,“玉大人,你說我怎么就攤上這事刀荒〈停” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵缠借,是天一觀的道長干毅。 經(jīng)常有香客問我,道長泼返,這世上最難降的妖魔是什么硝逢? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮绅喉,結(jié)果婚禮上渠鸽,老公的妹妹穿的比我還像新娘。我一直安慰自己柴罐,他們只是感情好徽缚,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著革屠,像睡著了一般凿试。 火紅的嫁衣襯著肌膚如雪排宰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天那婉,我揣著相機(jī)與錄音板甘,去河邊找鬼。 笑死详炬,一個胖子當(dāng)著我的面吹牛虾啦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播痕寓,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼呻率!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起呻引,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤礼仗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后逻悠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體元践,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年童谒,在試婚紗的時候發(fā)現(xiàn)自己被綠了单旁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡饥伊,死狀恐怖象浑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情琅豆,我是刑警寧澤愉豺,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站茫因,受9級特大地震影響蚪拦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜冻押,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一驰贷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧翼雀,春花似錦饱苟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽类垦。三九已至,卻和暖如春城须,著一層夾襖步出監(jiān)牢的瞬間蚤认,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工糕伐, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留砰琢,地道東北人。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓良瞧,卻偏偏與公主長得像陪汽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子褥蚯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359