John Jiang

          a cup of Java, cheers!
          https://github.com/johnshajiang/blog

             :: 首頁 ::  :: 聯系 :: 聚合  :: 管理 ::
            131 隨筆 :: 1 文章 :: 530 評論 :: 0 Trackbacks
          Maven入門--較復雜的實例
          本文將使用一個較復雜的實例,講述如何定制目錄布局(即不使用Maven標準目錄布局),以及講述一些關鍵插件的使用(配置)。為了方便其它朋友能夠方便地使用該實例,后臺數據庫使用開源的面向對象數據庫--db4o,該數據庫無需安裝,已包含在與本文配套的實例中,文末附有該實例的下載鏈接。(2007.01.02最后更新)
          注:轉載時請注明原作者(jiangshachina)及出處(http://www.aygfsteel.com/jiangshachina)!

          1 實例的構想
          文章開頭的摘要已經講述了,本文仍然將以一個實例描述如何使用Maven,
          該實例將使用非Maven標準的目錄結構,并將呈現一些關鍵的Maven插件的配置與應用。 該實例是一個基于db4o的數據庫Web應用。該應用本身十分簡單,即從db4o數據庫中查詢出若干記錄并將它們顯現在Web頁面中。
              該實例仍然由一個普通應用工程(demo-app)與一個Web應用工程(demo-web),以及這兩個工程的父工程(demo)構成,最終的目標是將Web應用工程制作成war文件,并部署到JBoss服務器中。啟動服務器后,能夠在頁面中看到正確的查詢結果。
              該實例使用Eclipse3.2 + JDK1.5.0_10 + Windows2000開發。當然這僅僅只是我個人的開發平臺,但該實例并不受限于此平臺;由于我選擇使用db4o針對JDK1.5的產品包,所以該實例只能運行在JDK1.5.0或更高版本的JDK/JRE中; 該工程中的所有文件都使用UTF-8編碼方式。

          2 demo工程
          demo工程是其它兩個工程的父工程,它的主要職責是預定義子工程所需要依賴的jar文件(artifact),以及針對子工程所使用的插件進行通用配置。該工程完整的POM文件如下所示:
          <project>
              <modelVersion>4.0.0</modelVersion>
              <groupId>mvn.demo</groupId>
              <artifactId>demo</artifactId>
              <packaging>pom</packaging>
              <version>
          1.0-SNAPSHOT</version>
              <description>Maven Demo Project</description>

              <modules>
                  <module>demo-app</module>
                  <module>demo-web</module>
              </modules>

              <dependencyManagement>
                  <dependencies>
                      <dependency>
                          <groupId>mvn.demo</groupId>
                          <artifactId>demo-app</artifactId>
                          <version>${project.version}</version>
                      </dependency>
                      <dependency>
                          <groupId>mvn.demo</groupId>
                          <artifactId>demo-web</artifactId>
                          <version>${project.version}</version>
                      </dependency>
                      <dependency>
                          <groupId>com.db4o</groupId>
                          <artifactId>db4o-java5</artifactId>
                          <version>
          5.5</version>
                      </dependency>
                      <dependency>
                          <groupId>javax.servlet</groupId>
                          <artifactId>servlet-api</artifactId>
                          <version>
          2.4</version>
                          <scope>provided</scope>
                      </dependency>
                      <dependency>
                          <groupId>commons-configuration</groupId>
                          <artifactId>commons-configuration</artifactId>
                          <version>
          1.2</version>
                          <exclusions>
                              <exclusion>
                                  <groupId>dom4j</groupId>
                                  <artifactId>dom4j</artifactId>
                              </exclusion>
                              <exclusion>
                                  <groupId>xml-apis</groupId>
                                  <artifactId>xml-apis</artifactId>
                              </exclusion>
                              <exclusion>
                                  <groupId>xalan</groupId>
                                  <artifactId>xalan</artifactId>
                              </exclusion>
                              <exclusion>
                                  <groupId>xerces</groupId>
                                  <artifactId>xercesImpl</artifactId>
                              </exclusion>
                          </exclusions>
                      </dependency>
                  </dependencies>
              </dependencyManagement>

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

              <build>
                  <plugins>
                      <plugin>
                          <groupId>org.apache.maven.plugins</groupId>
                          <artifactId>maven-resources-plugin</artifactId>
                          <configuration>
                              <encoding>UTF-
          8</encoding>
                          </configuration>
                      </plugin>

                      <plugin>
                          <groupId>org.apache.maven.plugins</groupId>
                          <artifactId>maven-compiler-plugin</artifactId>
                          <configuration>
                              <source>
          1.5</source>
                              <target>
          1.5</target>
                              <encoding>UTF-
          8</encoding>
                          </configuration>
                      </plugin>

                      <plugin>
                          <groupId>org.apache.maven.plugins</groupId>
                          <artifactId>maven-jar-plugin</artifactId>
                          <configuration>
                              <archive>
                                  <addMavenDescriptor>false</addMavenDescriptor>
                              </archive>
                          </configuration>
                      </plugin>

                      <plugin>
                          <groupId>org.apache.maven.plugins</groupId>
                          <artifactId>maven-war-plugin</artifactId>
                          <configuration>
                              <archive>
                                  <addMavenDescriptor>false</addMavenDescriptor>
                              </archive>
                          </configuration>
                      </plugin>

                      <plugin>
                          <groupId>org.apache.maven.plugins</groupId>
                          <artifactId>maven-javadoc-plugin</artifactId>
                          <configuration>
                              <charset>UTF16</charset>
                          </configuration>
                      </plugin>
                  </plugins>
              </build>
          </project>
              預定義工程的依賴關系,就是把會被子工程依賴的artifact的詳細信息(groupId,artifactId,version,...)先聲明到<dependencyManagement>中。然后子工程只需要聲明使用某個artifact就可以了,即那時只需要設置groupId和artifactId(甚至更少)就可以了。
          <dependencyManagement>中聲明的artifact并不一定真的會被使用到
          2.1 聲明依賴關系
              根據實際情況,
          該實例 需要使用db4o針對java5的產品包(jar文件)。由于該jar文件并不存在于Maven的中央倉庫中,所以我們不能直接通過Maven獲得該jar文件。我們只能另外下載db4o-5.5(Java版)的壓縮包,然后從壓縮包內獲得db4o-java5.jar。得到該jar后,必須先將它安裝到Maven的本地倉庫中(安裝方法參見資源[1],主題"向本地倉庫安裝文件時要生成POM文件"),以備后面的使用。此處將該artifact的groupId定義為com.db4o,artifactId定義為db4o-java5,version自然就是5.5了(請見上述POM腳本)。
              由于該實例最終是一個Web應用,所以它至少需要依賴Servlet的包(servlet-api-2.4.jar),還需要commons-configuration-1.2.jar。這兩個artifact都已經存在于Maven中央倉庫中,所以我查找到它們后,按照Maven中央倉庫的命名將它們聲明到了<dependencyManagement>中(請見上述POM腳本)。junit是進行單元測試時使用的artifact,(假設)它肯定會被每個工程使用,所以沒有將它設置到 <dependencyManagement>中,而直接設置到了 <dependency>中。
              細心的朋友肯定已經發現了,針對 commons-configuration的依賴聲明處多了一些語句。從表面上看,應該是排除了4個artifact(dom4j, xml-apis xalan xerces )。不錯,就是排除了這4個jar文件(artifact)。如果有興趣的話,可以將整個<exclusions>元素刪除,然后再嘗試一下制作war文件。你會發現在WEB-INF/lib目錄下存在著這4個artifact對應的jar文件。那我為什么要將它們“排除”呢?因為,它們是多余的!即,它們對于我的這個Web應用來說,根本就是無用的!
              Maven2加入了一個很好的特性:自動加載“依賴的依賴(Transitive Dependency)”。以commons-configuration為例。為了能夠讓它運行正常,我們實際上還需要其它一些jar(artifact),如commons-collections,commons-lang,...。但這些artifact我都沒有“顯示”地聲明需要依賴它們,但Maven會自動加載,因為
          commons-configuration的POM文件將它們聲明為了dependency
              既然那個4個artifact是commons-configuration的依賴,為什么會認為它們是無用的呢?實際上,它們就不應該被聲明到commons-configuration的依賴關系中。這是commons-configuration開發者的失誤,他們沒有將依賴關系整理清晰,而將一些確實既不是runtime,更不是compile-time需要的artifact放入到了依賴關系中。在Maven中央倉庫中存在著很多這種情況,所以我們有時需要弄清楚“哪些文件是我們真正需要的,哪些是可以被清除的”。但有時候,很難做到一個不漏。正是由于這一原因,自動加載Transitive Dependency這一極好的特性,有時讓人十分無奈 ^_^
          2.2 對插件進行基本配置
          我們可以把對插件的全局性(如針對整個項目的)設置放到較高層次的POM文件中,因為它們被設置后,子工程們就會自然遵守它們,而且可以使每個子工程的情況都是一樣的。
              在第1節中,已經表明該工程使用JDK1.5平臺,并且所有文件都使用UTF-8
          的編碼方式。而Maven默認使用JDK1.3級別的javac編譯器;默認使用本地編碼方式(簡體中文Windows操作系統默認使用GBK編碼方式)處理文件。這樣就必須對Maven進行適當設置,以滿足工程的實際需要。
              針對資源文件的處理,Maven使用maven-resources-plugin插件,需要將它的編碼方式設置為UTF-8。編譯Java源文件,是使用maven-compiler-plugin插件,需要將它的source(Java源文件)與target(class文件)的級別都設置為1.5,另外還要將它的encoding方式設置為UTF-8。(詳細設置請見POM腳本)

          3 demo-app工程
          demo-app工程是一個普通應用程序工程,它用于處理和數據庫相關的操作,如針對數據庫的增、刪、改、查等基本功能。該工程POM文件的主要內容如下所示:
          <project>
              ......

              <build>
                  <finalName>app</finalName>
                  <directory>target</directory>

                  <sourceDirectory>src/java</sourceDirectory>
                  <outputDirectory>target/classes</outputDirectory>
                  <resources>
                      <resource>
                          <directory>src/java</directory>
                          <excludes>
                              <exclude>**/*.java</exclude>
                          </excludes>
                      </resource>
                  </resources>

                  <testSourceDirectory>src/test/java</testSourceDirectory>
                  <testOutputDirectory>target/test-classes</testOutputDirectory>
                  <testResources>
                      <testResource>
                          <directory>src/test/java</directory>
                          <excludes>
                              <exclude>**/*.java</exclude>
                          </excludes>
                      </testResource>
                  </testResources>
              </build>
          </project>
              文章的開頭已經提到,本實例將會使用定制的目錄結構,但在前面卻一字不提此事,現在將描述如何定制目錄結構。Maven的標準目錄結構其實是在Super POM中設置的,由于任何POM都會繼承該POM,所以所有的工作都會默認使用標準目錄結構。要定制目錄,其實就是需要重新設置相關參數的值,即用新值覆蓋Super POM中的值。
          [1]<finalName>,該元素指定了工程輸出的artifact的名稱,默認值為${artifactId}-${version},此處修改為app。
          [2]<directory>,該元素指定了工程輸出的目標目錄。默認值為target,此處未修改變。
          [3]<sourceDirectory>,該元素指定了Java源文件所在的目錄。默認值為src/main/java,此處修改為src/java。
          [4]<outputDirectory>,該元素指定了編譯后的class文件的放置目錄。默認值為target/classes,此處未作改變。
          [5]<resources> <resource>,該元素指定了Java源文件使用的資源文件的存放目錄。默認值為src/main/resources,此處修改為src/java。由于在編碼Java源文件時,Maven會將資源路徑中的文件全部拷貝到classes目錄。而此時將Java資源文件目錄與Java源文件目錄,設置為同一目錄,所以需要將.java文件排除在資源文件的范疇之外( <exclude>**/*.java</exclude> )。
          [6]
          <testSourceDirectory>,該元素指定了單元測試Java源文件的放置目錄。默認值為src/test/java,此處未作修改。
          [7]
          <testOutputDirectory>,該元素指定了單元測試Java源文件編譯后的class文件放置目錄。默認值為 target/test-classes,此處未作改變。
          [8]
          <testResources> <testResource>,該元素指定了單元測試Java源文件所使用的資源文件的放置目錄。默認值為src/test/resources,此處修改為 src/test/java。并且也做了與 設置<resources> <resource>時相同的處理(排除Java源文件)。
              通過上述設置后,就可以擁有一個定制的Maven工程目錄結構了。

          4 demo-web工程
          demo-web工程是整個應用最終的目標輸出,因為此處的目的就是制作一個war文件,然后將它部署到JBoss服務器中。與demo-app工程相比,demo-web工程的POM文件主要有如下不同內容:
          <project >
              ......
              <build>
                  ......
                  <plugins>
                      <plugin>
                          <groupId>org.apache.maven.plugins</groupId>
                          <artifactId>maven-war-plugin</artifactId>
                          <version>
          2.0.1 </version>
                          <configuration>
                              <webappDirectory>target/${artifactId}</webappDirectory>
                              <warSourceDirectory>src/webapp</warSourceDirectory>
                          </configuration>
                      </plugin>

                      <plugin>
                          <groupId>org.codehaus.mojo</groupId>
                          <artifactId>jboss-maven-plugin</artifactId>
                          <version>
          1.3.1 </version>
                          <configuration>
                              <jbossHome>E:/jboss-
          4.0.2 </jbossHome>
                              <serverName>default</serverName>
                              <fileName>
                                  ${project.build.directory}/${project.build.finalName}.${project.packaging}
                              </fileName>
                          </configuration>
                      </plugin>
                  </plugins>
              </build>
          </project>
          可以看出不同之處就在于對maven-war-plguin及jboss-maven-plugin插件的配置與使用。
              Maven使用maven-war-plugin插件對Web工程制作war文件。由于本文使用了定制目錄結構,這樣則會使maven-war-plugin無法找到Web工程的Web Root目錄(默認是src/main/webapp),所以需要對該插件進行適當地配置。<warSourceDirectory>就是Web工程的Web Root目錄,此處設置為;<webappDirectory>是制作war文件之前,相當于是一個被打開(exploded)的war文件的根目錄(默認是target/artifactId-version)。
              該工程的腳本中,還使用了一個JBoss插件。該插件可以將制作好的war文件部署(實質上是拷貝)到指定的JBoss部署目錄中。<jbossHome>是JBoss的安裝根目錄,<serverName>指JBoss Server的名稱,<fileName>是被部署war文件的名稱。

          參考資源
          [1]Maven入門--概念與實例. http://www.aygfsteel.com/jiangshachina/archive/2006/09/01/67080.html
          [2]Maven + Continuum Weed. http://www.aygfsteel.com/jiangshachina/archive/2006/09/11/68944.aspx
          [3]Maven POM Reference. http://maven.apache.org/pom.html
          [3]db4o. http://www.db4objects.com
          本文實例下載地址--http://www.aygfsteel.com/files/jiangshachina/mvn-demo.rar

          posted on 2006-12-12 18:03 John Jiang 閱讀(12720) 評論(21)  編輯  收藏 所屬分類: JavaSEDatabaseMavendb4o原創

          評論

          # re: Maven入門--較復雜的實例 2006-12-18 00:48 Joeaniu
          贊,寫得很清晰~   回復  更多評論
            

          # re: Maven入門--較復雜的實例 2006-12-18 08:48 Sha Jiang
          謝謝夸獎 ^_^
          本文我將會進行修改,還有些內容沒有介紹到。
          而且不必將每個工程的POM文件完整內容帖上來,只需要針對特定的腳本片斷進行說明就可以了。POM的完整內容應該是看源文件的。  回復  更多評論
            

          # re: Maven入門--較復雜的實例 2006-12-20 21:30 向大家學習
          學習了 寫的很好  回復  更多評論
            

          # re: Maven入門--較復雜的實例 2006-12-23 18:31 Sha Jiang
          剛剛在IBM的developerWorks中看到一篇介紹Maven2的好文章,不敢獨享 ^_^
          http://www-128.ibm.com/developerworks/edu/j-dw-java-mavenv2.html?S_TACT=105AGX02&S_CMP=HP
          不過,需要首先注冊才能閱讀全文。  回復  更多評論
            

          # re: Maven入門--較復雜的實例 2007-06-24 23:01 sitinspring
          很好,很詳細,值得學習.

            回復  更多評論
            

          # re: Maven入門--較復雜的實例 2007-06-25 08:15 Sha Jiang
          謝謝!  回復  更多評論
            

          # re: Maven入門--較復雜的實例 2007-06-28 16:49 sitinspring
          我用Maven一直有一個疑惑,就是文件總是需要拷貝來拷貝去,只有用Bat或者Srcipt解決,但也麻煩,不只你是如何解決這個問題的?用Continuun能否避免這個麻煩?
            回復  更多評論
            

          # re: Maven入門--較復雜的實例 2007-06-29 08:53 Sha Jiang
          > 我用Maven一直有一個疑惑,就是文件總是需要拷貝來拷貝去,
          > 只有用Bat或者Srcipt解決,但也麻煩,不只你是如何解決這個問題的?
          不明白你的意思?
          為什么要將文件"拷貝來拷貝去"?只要把它們放到"合適"的地方就可以了啊。
          Bat肯定是不用的,否則無法將這個工程移植到其它地方(Linux中能用bat文件嗎?)。
          Script?如果你是指Ant的腳本,有時會用一些,但應該將它的數量保持在一個很小的水平上。

          > 用Continuun能否避免這個麻煩?
          Continuum是持續集成服務器,它只會根據Maven(也其它幾種build工具)工程中的Maven腳本去執行具體的Build工作。
          所以這個問題與Continuum無關,關鍵是在Maven本身。

          P.S.
          如果你看了我的其它"留言回復"的話,就會知道我是使用CruiseControl。
          Continuum集成Maven工程十分簡便,但它的功能目前還較弱,而且CC作為最老牌的持續集成工具,使用的范圍很廣,所以最好還是決定使用CC。  回復  更多評論
            

          # re: Maven入門--較復雜的實例 2007-06-29 08:57 Sha Jiang
          > 所以最好還是決定使用CC
          No No No,寫錯了,不是"最好",應該是"最后"。
          一字之差,千里之謬。  回復  更多評論
            

          # re: Maven入門--較復雜的實例[未登錄] 2007-06-29 15:43 sitinspring
          Thanks! I will try it.  回復  更多評論
            

          # re: Maven入門--較復雜的實例 2007-07-02 08:22 Sha Jiang
          Good Luck!  回復  更多評論
            

          # re: Maven入門--較復雜的實例(原) 2007-10-15 14:37 嶺南
          使用這個東東覺得很不爽,寫一大堆配置
          還時不時要到命令行下去搞一伙。
          覺得反而不方便。
          用Myeclipse一下全搞定。  回復  更多評論
            

          # re: Maven入門--較復雜的實例(原) 2007-10-15 17:18 Sha Jiang
          to 嶺南:
          與使用Ant相比,Maven的學習難度要稍大一些。
          但弄懂Maven的基本原理/應用后,再使用它,就不會覺得困難了。

          而且不可否認的是,Maven對于開發者的友好性也確實要差一些。
          Maven的標準目錄結構可能與開發者的習慣或所用開發工具的特性有沖突。
          通過定制目錄結構應該可以較好的解決這個問題。
          而且Maven的標準目錄結構本身就有利于開發,所以也不應該對它進行大的修改。  回復  更多評論
            

          # re: Maven入門--較復雜的實例(原) 2008-04-21 16:39 chamborghini
          受益匪淺,收藏了  回復  更多評論
            

          # re: Maven入門--較復雜的實例(原) 2008-12-25 09:56 Yvon
          寫得蠻好,謝謝  回復  更多評論
            

          # re: Maven入門--較復雜的實例(原) 2009-06-24 16:44 kting
          寫的很好,很有價值,受益。  回復  更多評論
            

          # re: Maven入門--較復雜的實例(原) 2010-12-02 15:46 Rosen
          感謝選用db4o做demo:)  回復  更多評論
            

          # re: Maven入門--較復雜的實例(原) 2011-09-14 15:53 Tony.Wang
          我看上的是可以對幾個工程統一編譯和打包,這個相對ANT就好多了,研究了兩三天,知道些皮毛了,看來要好好實踐一個復雜的例子試試了  回復  更多評論
            

          # re: Maven入門--較復雜的實例(原)[未登錄] 2012-10-03 16:16 tony
          再次感謝樓主  回復  更多評論
            

          # re: Maven入門--較復雜的實例(原) 2014-04-29 17:45 Gemma
          我運行demo的實例的時候報錯,說設備未就緒。
          好像是數據庫的問題,第一次接觸db4o,
          請問dbFile=D:/Download/book.yap這個文件在哪?  回復  更多評論
            

          # re: Maven入門--較復雜的實例(原) 2014-04-29 17:54 Sha Jiang
          @Gemma
          貌似這個問題已經存在七年多的時間了@_@
          不過,程序是否能最終運行成功,其實也無所謂吧。你可以修改下源代碼。
          另外,你們為什么不用Gradle呢?Maven有被它取代的趨勢。  回復  更多評論
            

          主站蜘蛛池模板: 绥中县| 平山县| 息烽县| 姜堰市| 买车| 金门县| 罗城| 金坛市| 建始县| 无为县| 双流县| 泾源县| 屏东县| 新泰市| 永平县| 白水县| 涿州市| 襄垣县| 汉中市| 射洪县| 黄冈市| 西林县| 南漳县| 西平县| 漳平市| 永春县| 晋州市| 剑河县| 阿拉善左旗| 漳州市| 张家口市| 和平区| 湄潭县| 富阳市| 平昌县| 出国| 项城市| 巴彦淖尔市| 青龙| 顺平县| 新密市|