Maven多模塊佈局實例詳解

Maven多模塊佈局實例詳解

一、開場白

使用Maven有段時間了,只能感慨真是個好東西,讓我從傳統模式體會到了嚴謹、規範、敏捷、方便的特性。 如果你懂Maven或許看過Juven翻譯的《Maven權威指南》; 發個牢騷:由於Maven的出身問題導致學習曲線陡峭,所有有些人就開始說Maven不好用;原因有二:一是排斥Maven,二是沒有耐心和精下心來學習,引用老毛的話來提醒我說的那些人:

沒有調查就沒有發言權

到了Maven這裏就是(適用於技術方面):

沒有深入學習也沒有發言權

如果Maven不好那麼Spring、Hibernate這些大家經常使用的框架爲什麼還是從ant轉移到Maven? 如果Maven不好那麼爲什麼國外大多數項目都在使用Maven呢? 原因自己考慮,我不廢話!我的這些話就是告誡那些信口雌黃的人。

二、多模塊佈局概述

詳細屬性Maven的童鞋們都看過《Maven權威指南》,裏面也講解如何搭建多模塊的Maven項目,但是那個畢竟是比較簡單的,在實際應用中就有點水土不服了; 後來又參考了Juven的一篇《Maven最佳實踐:劃分模塊》博文,相對權威指南來說介紹的比較詳細了,但是這還是不能滿足我真正在企業應用的需求,等你看完Juven的博文後再看看下面這個實際應用中的項目佈局有什麼異同:

Maven多模塊佈局概圖

OK,現在應該看出來有什麼不同了,我的項目結構比權威指南里面的介紹複雜、比Juven的那篇文章說的也複雜,接下來再看看這張圖片:

plexus-security項目結構

上面這張圖片是我在寫這篇文章的時候剛剛找到的:《按需構建多模塊,玩轉Maven反應堆》,和上面的Maven多模塊佈局概圖對比一下是不是基本一樣?真是後悔當初怎麼沒有看到Juven的這篇文章,後來把hibernate的項目checkout下來分析他的maven多模塊結構佈局然後再結合實際應用得出的Maven多模塊佈局概圖。 OK,現在你對多模塊佈局有了初步的印象了,接下來纔是重點,逐個擊破、逐個分析。

三、多模塊佈局詳解

無圖無真相,有圖纔給力:(如果想真正瞭解多模塊那麼請先看着圖片和說明揣摩一下含義……)

Maven多模塊佈局概述圖

聲明:由於是本例是根據實際應用的項目來分析的,所以會比之前說的教程和Juven的文章實例複雜一些。

  1. denong-pb:先看實例pom.xml:
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    <!--?xml version="1.0" encoding="UTF-8"?-->
        <modelversion>4.0.0</modelversion>
        <groupid>com.wsria</groupid>
        <artifactid>dn-pb</artifactid>
        <version>1.0.5-SNAPSHOT</version>
        <name>Denong Point Bank</name>
        <packaging>pom</packaging>
         
        <!-- 設定團隊持續集成發佈包服務器  -->
        <distributionmanagement>
            <repository>
                <id>nexus</id>
                <name>Team Nexus Release Repository</name>
            </repository>
            <snapshotrepository>
                <id>nexus</id>
                <name>Team Nexus Snapshot Repository</name>
                <uniqueversion>false</uniqueversion>
            </snapshotrepository>
        </distributionmanagement>
         
        <scm>
            <connection>scm:svn:https://192.168.1.111:8443/svn/denong/pb/trunk</connection>
        </scm>
         
        <modules>
            <module>parent</module>
            <module>common</module>
            <module>entity</module>
            <module>data</module>
            <module>dao</module>
            <module>service</module>
            <module>web-parent</module>
            <module>web-admin</module>
            <module>web-site</module>
        </modules>
         
        <build>
            <defaultgoal>install</defaultgoal>
            <plugins>
                <plugin>
                    <groupid>org.apache.maven.plugins</groupid>
                    <artifactid>maven-release-plugin</artifactid>
                    <version>2.0-beta-9</version>
                    <configuration>
                        <autoversionsubmodules>true</autoversionsubmodules>
                    </configuration>
                </plugin>
            </plugins>
      </build>
       
    </project>
  2. bin可有可無,存放一些maven的命令批處理文件或者快捷bat文件,比如本地install項目或者打包根據產品profile(在模塊中配置id爲product的profile)打包war;
  3. common:估計有一些經驗的人都會把一些常用的工具類封裝起來,由經驗豐富的人來維護到common模塊中作爲技術沉澱和公司的公共類庫,方便大家快速開發使用。當然實際應用中可能會使用公司已經存在的common模塊,然後單個項目中可能會再加入一個common模塊,一般公司的common包都是這麼積累下來的;
  4. dao:每個模塊的數據存取類,因爲本項目是根據springside基礎上構建的,所以都是繼承HibernateDao,如果涉及到大數據量或者存儲過程的調用會再加入相應的*JdbcDao;
  5. datadata模塊結構,根據上圖介紹一下:除了data目錄外其他的配置文件都是在測試期間使用的,根據不同需求使用不同配置文件,例如一些不需要spring啓動時初始化的數據使用applicationContext-test-no-init-sql.xml,這個沒有什麼規定,根據項目來設置;data目錄是存放一些使用dbunit導出的xml數據文件,作用是在單元測試時的數據初始化或者利用數據文件初始化指定的數據庫,一般這些數據文件的類型包括:數據字典、系統配置參數等
  6. entity:這裏說一下JPA註解的實體工具,開始我使用的是eclipse3.6的JPA工具,但是發現有些屬性加不上@Column註解很是鬱悶,只能手動加入;當然你也可以使用springside中提供的hibernatetools模板生成,但是我還是希望在生成期間能完全受控,所以最好想到了MyEclipse,配置好數據源然後從數據庫中逆向生成JPA,所有字段都正確配置;
  7. parent:這裏着重介紹一下,此模塊是所有子模塊需要繼承的超級POM,舉個例子容易理解:把本項目(denong-pb)當做是Java語言,那麼parent模塊就是Object類,此模塊只負責定影其他子模塊需要使用的一些公共設置,謹記:
    parent不負責管理子模塊,只是被子模塊集成,千萬不要和denong-pb目錄的pom.xml混淆
  8. service:就是業務處理類,供web模塊調用;
  9. web-parent:供web*模塊繼承,例如前後臺都需要調用的Action接口,像數據字典、地區信息、系統屬性等
  10. web-admin:系統的後臺管理程序,使用了struts2的convention插件;
  11. web-site:系統網站部分,同樣使用了struts2的convention插件,集成單點登錄功能

四、模塊之間依賴關係

直觀教程圖片最給力: Maven多模塊關係依賴圖

五、和SVN的整合——maven-release-plugin

maven-release-plugin是經常使用的插件,這裏簡單介紹一下,要點:

  1. 每個模塊的scm配置
    ?
    1
    2
    3
    4
    <scm>
        <connection>scm:svn:https://192.168.1.111:8443/svn/denong/pb/trunk/模塊名稱</connection>
        <url>https://192.168.1.111:8443/svn/denong/pb/trunk/模塊名稱</url>
    </scm>
    上面的scm配置在每一個模塊中存在,因爲每一個模塊再svn目錄中有單獨的目錄;
    但是parent模塊有點不同,因爲除了parent模塊其他子模塊需要繼承parent,如下代碼:
    ?
    1
    2
    3
    4
    5
    6
    7
    <parent>
        <groupid>com.wsria</groupid>
        <artifactid>parent</artifactid>
        <version>1.0.5-SNAPSHOT</version>
        <relativepath>../parent/pom.xml</relativepath>
    </parent>
    <artifactid>dn-pb-entity</artifactid>
    parent模塊設定了一些被子模塊集成的插件,maven-release-plugin當然也在列,除了GAV之外最重要的就是tagBase標籤:
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!-- release插件 -->
    <plugin>
        <groupid>org.apache.maven.plugins</groupid>
        <artifactid>maven-release-plugin</artifactid>
        <version>2.0-beta-9</version>
        <configuration>
            <tagbase>https://192.168.1.111:8443/svn/denong/pb/tags/</tagbase>
            <username>${svn.name}</username>
            <password>${svn.pwd}</password>
        </configuration>
    </plugin>
    本地的settings.xml中配置(替換${svn.name}和${svn.pwd},也就是svn提交時的用戶名和密碼):
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <settings>
    ...
    <profiles>
        <profile>
            <id>denong-product</id>
            <properties>
                <svn.name>kafeitu</svn.name>
                <svn.pwd>123456</svn.pwd>
            </properties>
        </profile>
    </profiles>
    ...
    </settings>
    在denong-pb目錄中執行命令:
    D:\wsria\projects\denong\denong-pb>mvn release:prepare -Pdenong-product
    在svn中自動打的tag結構爲: maven-release-plugin執行release:prepare後的svn結構接下來就可以執行命令:
    D:\wsria\projects\denong\denong-pb>mvn release:perform

六、多模塊佈局問題

如果你夠細心可能發現了上面出現了relativePath屬性,這個再多模塊的配置中經常遇到的問題,根據目前的案例來說子模塊和parent是同級的目錄,但是每個子模塊又都需要繼承parent模塊的一些配置,比如上面介紹的到common模塊會使用如下配置:

?
1
2
3
4
5
6
<parent>
    <groupid>com.wsria</groupid>
    <artifactid>parent</artifactid>
    <version>1.0.5-SNAPSHOT</version>
</parent>
<artifactid>common</artifactid>

現在問題來了,在common模塊下執行命令:mvn compile,得到的結果中包含了警告信息:

[WARNING] 'parent.relativePath' points at com.wsria:dn-pb instead of com.wsria:dn-pb-parent, please verify your project structure @ line 4, column 10

意思是找不到dn-pb-parent這個模塊……因爲maven不知道dn-pb-parent模塊存在的位置纔會導致警告信息的出現,解決辦法是手動指定dn-pb-parent模塊的位置,所以最終的解決辦法是在parent標籤中加入:

?
1
<relativepath>../parent/pom.xml</relativepath>

這樣maven就知道繼承的parent的具體位置了,

relativePath默認值爲../pom.xml,參考:http://maven.apache.org/ref/3.0/maven-model/maven.html

完整的parent繼承配置:

?
1
2
3
4
5
6
7
<parent>
    <groupid>com.wsria</groupid>
    <artifactid>dn-pb-parent</artifactid>
    <version>1.0.5-SNAPSHOT</version>
    <relativepath>../parent/pom.xml</relativepath>
</parent>
<artifactid>dn-pb-common</artifactid>

現在運行mvn命令一切正常了;

記得每一個繼承parent模塊的子模塊都需要添加relativePath設置

七、多模塊開發期間Debug

一般我們在開發web模塊的時候會啓用tomcat或者jboss的debug模式來斷點調試應用,但是你會發現如果web模塊依賴了service模塊想進入service模塊debug但是eclipse卻告訴你找不到class的源碼,解決辦法:

把service模塊加入到Build Path的Project列表中

八、其他方案

如何佈局是根據每一個項目組的安排定義的,比如

  1. 一個項目組分模塊開發的話或許不像本例一樣分模塊而是把每一層都集中在一個項目中
  2. 或許web模塊單獨一個子模塊,其他的entyty、dao、service集中在一個子模塊model中
怎麼佈局需要根據項目實際情況來定義,當然要考慮到單個子模塊的重複利用,例如service模塊在本例中被web-admin和web-site模塊使用,如果以後再加入webservice模塊那麼webservice也要依賴,或許還有命令行(command)模塊也要依賴

九、結束語

這是一篇難產的文章,有些原因影響經過了3個晚上纔出世,呵呵 有不對的地方請留言以改正; 分享這篇文章的目的就是給剛剛接觸或者正需要maven多模塊佈局的童鞋們參考,希望能對你有幫助,謝謝關注!

發佈了10 篇原創文章 · 獲贊 5 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章