<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Maven 劃分模塊最佳實(shí)踐

          共 6145字,需瀏覽 13分鐘

           ·

          2021-10-26 21:22

          所有用Maven管理的真實(shí)的項(xiàng)目都應(yīng)該是分模塊的,每個(gè)模塊都對(duì)應(yīng)著一個(gè)pom.xml。它們之間通過(guò)繼承和聚合(也稱(chēng)作多模塊,multi-module)相互關(guān)聯(lián)。那么,為什么要這么做呢?我們明明在開(kāi)發(fā)一個(gè)項(xiàng)目,劃分模塊后,導(dǎo)入Eclipse變成了N個(gè)項(xiàng)目,這會(huì)帶來(lái)復(fù)雜度,給開(kāi)發(fā)帶來(lái)不便。

          為了解釋原因,假設(shè)有這樣一個(gè)項(xiàng)目,很常見(jiàn)的Java Web應(yīng)用。在這個(gè)應(yīng)用中,我們分了幾層:

          • Dao層負(fù)責(zé)數(shù)據(jù)庫(kù)交互,封裝了Hibernate交互的類(lèi)。

          • Service層處理業(yè)務(wù)邏輯,放一些Service接口和實(shí)現(xiàn)相關(guān)的Bean。

          • Web層負(fù)責(zé)與客戶端交互,主要有一些Structs的Action類(lèi)。

          對(duì)應(yīng)的,在一個(gè)項(xiàng)目中,我們會(huì)看到一些包名:

          • org.myorg.app.dao

          • org.myorg.app.service

          • org.myorg.app.web

          • org.myorg.app.util

          這樣整個(gè)項(xiàng)目的框架就清晰了,但隨著項(xiàng)目的進(jìn)行,你可能會(huì)遇到如下問(wèn)題:
          這個(gè)應(yīng)用可能需要有一個(gè)前臺(tái)和一個(gè)后臺(tái)管理端(web或者swing),你發(fā)現(xiàn)大部分dao,一些service,和大部分util是在兩個(gè)應(yīng)用中可用的。這樣的問(wèn)題,你一周內(nèi)遇到了好幾次。
          pom.xml中的依賴(lài)列表越來(lái)越長(zhǎng)以重用的,但是,由于目前只有一個(gè)項(xiàng)目(WAR),你不得不新建一個(gè)項(xiàng)目依賴(lài)這個(gè)WAR,這變得非常的惡心,因?yàn)樵贛aven中配置對(duì)WAR的依賴(lài)遠(yuǎn)不如依賴(lài)JAR那樣簡(jiǎn)單明了,而且你根本不需要org.myorg.app.web。有人修改了dao,提交到svn并且不小心導(dǎo)致build失敗了,你在編寫(xiě)service的代碼,發(fā)現(xiàn)編譯不過(guò),只能等那人把dao修復(fù)了,你才能繼續(xù)進(jìn)行,很多人都在修改,到后來(lái)你根本就不清楚哪個(gè)依賴(lài)是誰(shuí)需要的,漸漸的,很多不必要的依賴(lài)被引入。甚至出現(xiàn)了一個(gè)依賴(lài)有多個(gè)版本存在。
          build整個(gè)項(xiàng)目的時(shí)間越來(lái)越長(zhǎng),盡管你只是一直在web層工作,但你不得不build整個(gè)項(xiàng)目。
          某個(gè)模塊,比如util,你只想讓一些經(jīng)驗(yàn)豐富的人來(lái)維護(hù),可是,現(xiàn)在這種情況,每個(gè)開(kāi)發(fā)者都能修改,這導(dǎo)致關(guān)鍵模塊的代碼質(zhì)量不能達(dá)到你的要求。
          我們會(huì)發(fā)現(xiàn),其實(shí)這里實(shí)際上沒(méi)有遵守一個(gè)設(shè)計(jì)模式原則:“高內(nèi)聚,低耦合”。雖然我們通過(guò)包名劃分了層次,并且你還會(huì)說(shuō),這些包的依賴(lài)都是單向的,沒(méi)有包的環(huán)依賴(lài)。這很好,但還不夠,因?yàn)榫蜆?gòu)建層次來(lái)說(shuō),所有東西都被耦合在一起了。因此我們需要使用Maven劃分模塊。

          一個(gè)簡(jiǎn)單的Maven模塊結(jié)構(gòu)是這樣的:

           1----?app-parent
          2|--?pom.xml?(pom)
          3|
          4|--?app-util
          5|????????|--?pom.xml?(jar)
          6|
          7|--?app-dao
          8|????????|--?pom.xml?(jar)
          9|
          10|--?app-service
          11|????????|--?pom.xml?(jar)
          12|
          13|--?app-web
          14|--?pom.xml?(war)

          上述簡(jiǎn)單示意圖中,有一個(gè)父項(xiàng)目(app-parent)聚合很多子項(xiàng)目(app-util, app-dao, app-service, app-web)。每個(gè)項(xiàng)目,不管是父子,都含有一個(gè)pom.xml文件。而且要注意的是,小括號(hào)中標(biāo)出了每個(gè)項(xiàng)目的打包類(lèi)型。父項(xiàng)目是pom,也只能是pom。子項(xiàng)目有jar,或者war。根據(jù)它包含的內(nèi)容具體考慮。

          這些模塊的依賴(lài)關(guān)系如下:

          1app-dao??????-->?app-util
          2app-service??-->?app-dao
          3app-web??????-->?app-service

          注意依賴(lài)的傳遞性(大部分情況是傳遞的,除非你配置了特殊的依賴(lài)scope),app-dao依賴(lài)于app-util,app-service依賴(lài)于app-dao,于是app-service也依賴(lài)于app-util。同理,app-web依賴(lài)于app-dao,app-util。

          項(xiàng)目層次的劃分代包層次的劃分能給我們帶來(lái)如下好處:

          • 方便重用,如果你有一個(gè)新的swing項(xiàng)目需要用到app-dao和app-service,添加對(duì)它們的依賴(lài)即可,你不再需要去依賴(lài)一個(gè)WAR。而有些模塊,如app-util,完全可以漸漸進(jìn)化成公司的一份基礎(chǔ)工具類(lèi)庫(kù),供所有項(xiàng)目使用。這是模塊化最重要的一個(gè)目的。

          • 由于你現(xiàn)在劃分了模塊,每個(gè)模塊的配置都在各自的pom.xml里,不用再到一個(gè)混亂的紛繁復(fù)雜的總的POM中尋找自己的配置。

          • 如果你只是在app-dao上工作,你不再需要build整個(gè)項(xiàng)目,只要在app-dao目錄運(yùn)行mvn命令進(jìn)行build即可,這樣可以節(jié)省時(shí)間,尤其是當(dāng)項(xiàng)目越來(lái)越復(fù)雜,build越來(lái)越耗時(shí)后。

          • 某些模塊,如app-util被所有人依賴(lài),但你不想給所有人修改,現(xiàn)在你完全可以從這個(gè)項(xiàng)目結(jié)構(gòu)出來(lái),做成另外一個(gè)項(xiàng)目,svn只給特定的人訪問(wèn),但仍提供jar給別人使用。

          • 多模塊的Maven項(xiàng)目結(jié)構(gòu)支持一些Maven的更有趣的特性(如DepencencyManagement),這留作以后討論。

          • 接下來(lái)討論一下POM配置細(xì)節(jié),實(shí)際上非常簡(jiǎn)單,先看app-parent的pom.xml

           1<project?xmlns="http://maven.apache.org/POM/4.0.0"?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          2xsi:schemaLocation="http://maven.apache.org/POM/4.0.0?http://maven.apache.org/maven-v4_0_0.xsd">

          3<modelVersion>4.0.0modelVersion>

          4<groupId>org.myorg.myappgroupId>
          5<artifactId>app-parentartifactId>
          6<packaging>pompackaging>
          7<version>1.0-SNAPSHOTversion>
          8<modules>
          9????<module>app-utilmodule>
          10????<module>app-daomodule>
          11????<module>app-servicemodule>
          12????<module>app-webmodule>
          13modules>
          14project>

          Maven的坐標(biāo)GAV(groupId,?artifactId,?version)在這里進(jìn)行配置,這些都是必須的。特殊的地方在于,這里的packagingpom。所有帶有子模塊的項(xiàng)目的packaging都為pom。packaging如果不進(jìn)行配置,它的默認(rèn)值是jar,代表Maven會(huì)將項(xiàng)目打成一個(gè)jar包。
          該配置重要的地方在于modules,例子中包含的子模塊有app-util, app-dao, app-service, app-war。在Maven build app-parent的時(shí)候,它會(huì)根據(jù)子模塊的相互依賴(lài)關(guān)系整理一個(gè)build順序,然后依次build。
          這就是一個(gè)父模塊大概需要的配置,接下來(lái)看一下子模塊符合配置繼承父模塊。

           1<project?xmlns="http://maven.apache.org/POM/4.0.0"?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          2xsi:schemaLocation="http://maven.apache.org/POM/4.0.0?http://maven.apache.org/maven-v4_0_0.xsd">

          3<parent>
          4<artifactId>app-parentartifactId>

          5<groupId>org.myorg.myappgroupId>
          6<version>1.0-SNAPSHOTversion>
          7parent>
          8<modelVersion>4.0.0modelVersion>
          9<artifactId>app-utilartifactId>
          10<dependencies>
          11????<dependency>
          12????????<groupId>commons-langgroupId>
          13????????<artifactId>commons-langartifactId>
          14????????<version>2.4version>
          15???dependency>
          16dependencies>
          17project>

          app-util模塊繼承了app-parent父模塊,因此這個(gè)POM的一開(kāi)始就聲明了對(duì)app-parent的引用,該引用是通過(guò)Maven坐標(biāo)GAV實(shí)現(xiàn)的。而關(guān)于項(xiàng)目app-util本身,它卻沒(méi)有聲明完整GAV,這里我們只看到了artifactId。這個(gè)POM并沒(méi)有錯(cuò),groupId和version默認(rèn)從父模塊繼承了。實(shí)際上子模塊從父模塊繼承一切東西,包括依賴(lài),插件配置等等。
          此外app-util配置了一個(gè)對(duì)于commons-lang的簡(jiǎn)單依賴(lài),這是最簡(jiǎn)單的依賴(lài)配置形式。大部分情況,也是通過(guò)GAV引用的。
          再看一下app-dao,它也是繼承于app-parent,同時(shí)依賴(lài)于app-util:

           1<project?xmlns="http://maven.apache.org/POM/4.0.0"?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          2xsi:schemaLocation="http://maven.apache.org/POM/4.0.0?http://maven.apache.org/maven-v4_0_0.xsd">

          3<parent>
          4<artifactId>app-parentartifactId>

          5<groupId>org.myorg.myappgroupId>
          6<version>1.0-SNAPSHOTversion>
          7parent>
          8<modelVersion>4.0.0modelVersion>
          9<artifactId>app-daoartifactId>
          10<dependencies>
          11???????<dependency>
          12?????????<groupId>org.myorg.myappgroupId>
          13?????????<artifactId>app-utilartifactId>
          14?????????<version>${project.version}version>
          15????dependency>
          16dependencies>
          17project>

          該配置和app-util的配置幾乎沒(méi)什么差別,不同的地方在于,依賴(lài)變化了,app-dao依賴(lài)于app-util。這里要注意的是version的值為${project.version},這個(gè)值是一個(gè)屬性引用,指向了POM的project/version的值,也就是這個(gè)POM對(duì)應(yīng)的version。由于app-dao的version繼承于app-parent,因此它的值就是1.0-SNAPSHOT。而app-util也繼承了這個(gè)值,因此在所有這些項(xiàng)目中,我們做到了保持版本一致。
          這里還需要注意的是,app-dao依賴(lài)于app-util,而app-util又依賴(lài)于commons-lang,根據(jù)傳遞性,app-dao也擁有了對(duì)于commons-lang的依賴(lài)。
          app-service我們跳過(guò)不談,它依賴(lài)于app-dao。我們最后看一下app-web:

           1<project?xmlns="http://maven.apache.org/POM/4.0.0"?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          2xsi:schemaLocation="http://maven.apache.org/POM/4.0.0?http://maven.apache.org/maven-v4_0_0.xsd">

          3<parent>
          4<artifactId>app-parentartifactId>

          5<groupId>org.myorg.myappgroupId>
          6<version>1.0-SNAPSHOTversion>
          7parent>
          8<modelVersion>4.0.0modelVersion>
          9<artifactId>app-webartifactId>
          10<packaging>warpackaging>
          11<dependencies>
          12????<dependency>
          13????????<groupId>org.myorg.myappgroupId>
          14????????<artifactId>app-serviceartifactId>
          15????????<version>${project.version}version>
          16????dependency>
          17dependencies>
          18project>

          app-web依賴(lài)于app-service,因此配置了對(duì)其的依賴(lài)。
          由于app-web是我們最終要部署的應(yīng)用,因此它的packaging是war。為此,你需要有一個(gè)目錄
          src/main/webapp。并在這個(gè)目錄下?lián)碛衱eb應(yīng)用需要的文件,如/WEB-INF/web.xml。沒(méi)有web.xml,Maven會(huì)報(bào)告build失敗,此外你可能還會(huì)有這樣一些子目錄:/js, /img, /css … 。

          看看Maven是如何build整個(gè)項(xiàng)目的,我們?cè)?app-parent 根目錄中運(yùn)行?mvn clean install?,輸出的末尾會(huì)有大致這樣的內(nèi)容:

           1...
          2...
          3[INFO]?[war:war]
          4[INFO]?Packaging?webapp
          5[INFO]?Assembling?webapp[app-web]?in?[/home/juven/workspaces/ws-others/myapp/app-web/target/app-web-1.0-SNAPSHOT]
          6[INFO]?Processing?war?project
          7[INFO]?Webapp?assembled?in[50?msecs]
          8[INFO]?Building?war:?/home/juven/workspaces/ws-others/myapp/app-web/target/app-web-1.0-SNAPSHOT.war
          9[INFO]?[install:install]
          10[INFO]?Installing?/home/juven/workspaces/ws-others/myapp/app-web/target/app-web-1.0-SNAPSHOT.war?to?/home/juven/.m2/repository/org/myorg/myapp/app-web/1.0-SNAPSHOT/app-web-1.0-SNAPSHOT.war
          11[INFO]
          12[INFO]
          13[INFO]?------------------------------------------------------------------------
          14[INFO]?Reactor?Summary:
          15[INFO]?------------------------------------------------------------------------
          16[INFO]?app-parent?............................................?SUCCESS?[1.191s]
          17[INFO]?app-util?..............................................?SUCCESS?[1.274s]
          18[INFO]?app-dao?...............................................?SUCCESS?[0.583s]
          19[INFO]?app-service?...........................................?SUCCESS?[0.593s]
          20[INFO]?app-web?...............................................?SUCCESS?[0.976s]
          21[INFO]?------------------------------------------------------------------------
          22[INFO]?------------------------------------------------------------------------
          23[INFO]?BUILD?SUCCESSFUL
          24[INFO]?------------------------------------------------------------------------
          25[INFO]?Total?time:?4?seconds
          26[INFO]?Finished?at:?Sat?Dec?27?08:20:18?PST?2008
          27[INFO]?Final?Memory:?3M/17M
          28[INFO]?------------------------------------------------------------------------

          注意Reactor Summary,整個(gè)項(xiàng)目根據(jù)我們希望的順序進(jìn)行build。Maven根據(jù)我們的依賴(lài)配置,智能的安排了順序,app-util, app-dao, app-service, app-web。

          最后,你可以在?app-web/target?目錄下找到文件?app-web-1.0-SNAPSHOT.war?,打開(kāi)這個(gè)war包,在?/WEB-INF/lib?目錄看到了 commons-lang-2.4.jar,以及對(duì)應(yīng)的app-util, app-dao, app-service 的jar包。Maven自動(dòng)幫你處理了打包的事情,并且根據(jù)你的依賴(lài)配置幫你引入了相應(yīng)的jar文件。

          使用多模塊的Maven配置,可以幫助項(xiàng)目劃分模塊,鼓勵(lì)重用,防止POM變得過(guò)于龐大,方便某個(gè)模塊的構(gòu)建,而不用每次都構(gòu)建整個(gè)項(xiàng)目,并且使得針對(duì)某個(gè)模塊的特殊控制更為方便。本文同時(shí)給出了一個(gè)實(shí)際的配置樣例,展示了如何使用Maven配置多模塊項(xiàng)目。


          喜歡,在看

          瀏覽 51
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产三级三级三级看三级囯产亚洲 | 国产又大又粗又黄 | 一区二区第三十七页 | 乱伦福利片 | 国产激情视频久久久久久久 |