使用maven構建基本的web項目結構

 

由於當前公司在組織進行項目基本結構的整理,將以前通過eclipse/ ant 方式構建的項目向maven上遷移,於是便進行maven項目方面的調研。

 

對於maven項目,基本的結構已經在標準文件中:

 

 
 
以及其翻譯成中文的相關文檔:
 
 
使用一套通用的目錄結構的好處是,可以減少開發人員熟悉不同Maven項目時的認知負擔。在使用相同的目錄結構的情況下,開發人員可以很快的熟悉一個項目。接下來,我們將開始介紹Maven的通用的目錄結構。
 

<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->

Maven默認約定了一套目錄結構,在通過Maven創建了項目以後,項目的目錄結構就是以這套目錄結構作爲模板創建的。
 
文檔中關於所有目錄結構的含義如下:
 
src/main/java Application/Library sources
src/main/resources Application/Library resources
src/main/filters Resource filter files
src/main/webapp Web application sources
src/test/java Test sources
src/test/resources Test resources
src/test/filters Test resource filter files
src/it Integration Tests (primarily for plugins)
src/assembly Assembly descriptors
src/site Site
LICENSE.txt Project's license
NOTICE.txt Notices and attributions required by libraries that the project depends on
README.txt Project's readme
 
 
<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
在一個Maven項目中,在項目根目錄下,除了包含了上面約定的目錄結構中的部分目錄外,還包含了項目描述文件,pom.xml文件。
 
在根目錄下,主要有兩個目錄,分別是src和target目錄,除此之外,還會有一些版本控制系統的元數據文件,包括git的.gitignore或者svn的.svn。如果一個項目時由多個子項目組成的,那麼在該項目的根目錄下,還會包含它的子項目的目錄。子項目的目錄佈局,默認也是和上面列出的目錄結構一致的。
 
在src目錄下,包含了項目所有的源代碼和資源文件,以及其他項目相關的文件。在該目錄的main目錄下,包含了構建該項目的artifact(可以理解爲時項目的程序部分)所需的代碼和資源,而test目錄包含了測試相關的代碼和資源文件。
 
在目錄main和test下的子目錄結構,是非常相似的,都包含了兩個子目錄:java子目錄和resources子目錄,這兩個目錄分別放了源代碼和資源文件。不同的是,在main目錄下的這兩個目錄中放置了項目主程序的代碼,而在test目錄下,放置的是測試相關的代碼和資源文件。其中java目錄是代碼的根目錄,在該目錄下的子目錄,就是Java的包名對應的目錄結構了。
 
討論:是否有必要在同一個項目下聲明多個source folder(源代碼目錄)?還是以包名來區分?
 
 
maven需要設置groupId和artifactId,其命名規則需要一起根據公司的策略制定一下。
 
由於當前我們使用git作爲版本控制工具,因此.gitignore文件必不可少,基於java項目的文件,考慮到使用eclipse和idea IDE工具都有對應的開發人員:
 
由於我們使用git作爲版本管理工具,在使用maven作爲build工具時,需要將IDE的工程描述文件以及項目生成的target/,bin/目錄忽略掉,因此.gitignore文件必不可少,以下內容可以作爲項目的.gitignore文件範本:

# generated files where run in local machine
bin/
target/

# eclipse project description files
.settings/
.project

# idea project description files
.idea/
*.iml

### Java template
*.class

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
 
最終整理的web項目結構如下(用idea作爲實例),由於使用SpringMVC,業務上增加了一些java package:
 


 
 
 
 
其他的目錄都比較容易理解,下面介紹一下src/main/filter目錄的作用:
  
構建項目的過程中,可能會對開發,測試,線上等不同的環境有着不同的設置,或資源,比較常見的是數據庫jdbc.properties配置,下面就以這個爲具體例子簡單介紹一下,參考了下面兩篇blog(已經講得非常詳細了)。
  
 
不同的軟件開發生命週期階段、不同的最終客戶(用戶)環境、不同的運行平臺都有可能需要不同配置或資源的情況。假如各個環境下的差別很小的話,我們可以在項目編譯之後手工修改或者寫個 shell script 自動修改,但如果需要修改的項目很多而且複雜的話,則應該使用 Apache Maven 的 Profile 和 Filtering 功能來解決
 
 
Profile 的作用是允許你在項目文件(pom.xml)裏定義若干個 profile 段,然後在編譯時選擇其中的一個用於覆蓋項目文件原先的定義,我們可以在pom文件中定義多個profile,分別表示開發(dev), 測試(test),以及線上(product)用來區分不同的執行環境。
 
<profiles>
    <profile>
      <id>dev</id>
      <properties>
        <active.profile>dev</active.profile>
      </properties>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
    </profile>

    <profile>
      <id>test</id>
      <properties>
        <active.profile>test</active.profile>
      </properties>
    </profile>

    <profile>
      <id>product</id>
      <properties>
        <active.profile>product</active.profile>
      </properties>
    </profile>
  </profiles>
 
上述設置中表示profile dev爲默認的profile,在idea編輯器中,執行maven編譯時,選擇對應的profile;profile不僅可以在項目中配置,還可以全局配置(下面的sonar就是在全局setting.xml中配置的)。
 


 
 
在pom.xml中聲明build標籤,用來加入filter文件,${active.profile}就表示當前使用的profile,在profile文件中被定義:
 
<build>
    <finalName>example</finalName>
    <filters>
      <filter>src/main/filters/filters-${active.profile}.properties</filter>
    </filters>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>
 
在src/main/filters目錄下存在三個文件:
  • filters-dev.properties
  • filters-test.properties
  • filters-product.properties
 
注意,名稱需要與profile的名稱保持一致,以滿足 filter-${active.profile}文件的通配符。
 
在src/main/resources目錄下的全局配置文件 jdbc.properties不指定具體的路徑,使用變量來定義:
 
dbc.url=${pom.jdbc.url}
jdbc.username=${pom.jdbc.username}
jdbc.passworkd=${pom.jdbc.password}
 
 
在filters-dev.properties文件就需要如此定義:
 
pom.jdbc.url=dev
pom.jdbc.username=dev
pom.jdbc.password=dev
 
這樣在執行maven 構建命令時,默認使用dev profile(默認設置爲true),或者通過-P product來產生生產環境下的war包。
 
可以定義多個profile來支持 開發環境/測試環境/生產環境 之間的文件屬性替換操作。
 
不同的軟件開發生命週期階段、不同的最終客戶(用戶)環境、不同的運行平臺都有可能需要不同配置或資源的情況。假如各個環境下的差別很小的話,我們可以在項目編譯之後手工修改或者寫個 shell script 自動修改,但如果需要修改的項目很多而且複雜的話,則應該使用 Apache Maven 的 Profile 和 Filtering 功能來解決
 
 
Profile 的作用是允許你在項目文件(pom.xml)裏定義若干個 profile 段,然後在編譯時選擇其中的一個用於覆蓋項目文件原先的定義。
 
或者另外一種方案,這是原來我們工程中大量被使用的方案,在build war包的時候,選擇將一些文件排除:
 
<sourceDirectory>src</sourceDirectory>
        <resources>
            <resource>
                <directory>src/main/resource</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                    <exclude>conf/**</exclude>
                </excludes>
            </resource>
            <resource>
                <directory>package/${package.environment}</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
 
 
這裏就會將resources/conf/目錄下的文件排除掉,但是此時需要使用其他文件進行頂替,這裏就包含了package/${package.environment}目錄下的配置文件。
 
配置文件中的package.environment變量是在profile中定義的,每個profile都有着不同的設置,例如dev、test環境就會有所不同。
 
<profiles>
        <profile>
            <id>dev</id>
            <properties>
                <package.environment>dev</package.environment>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <id>test</id>
            <properties>
                <package.environment>test</package.environment>
            </properties>
        </profile>
    </profiles>
 
 
項目目錄中都需要有一份完整的配置文件。
 


 
 
如果使用這種方式的話,其實是不知道每個環境的具體配置差異的,只是通過低級的配置文件複製來進行處理(類似於拷貝代碼),不利於我們將可變變量統一區分並管理起來,每次更新spring/mybatis配置都需要修改多處的配置文件(執行復制)。
 
但這種方式其實有個好處,就是我們在本地IDE執行時,可以不通過maven調用來進行(如果是Profile+Filter替換的話需要用maven來啓動jetty/tomcat)。
 
常用的maven jar包搜索工具: http://mvnrepository.com,如果不知道所在的jar包,也可以使用google進行站內搜索:
 
site:mvnrepository.com xxx.JavaClass,也可以將該搜索源作爲maven倉庫加入進去:
 
<repository>
      <id>mvnrepository</id>
      <name>mvnrepository</name>
      <url>http://www.mvnrepository.com</url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository> 
 
 
關於SnapShots和Release之間的區別,可以參考:http://yongpoliu.com/snapshot-vs-release/
 
對於release版本,我們不能強制將其刷新,maven -U參數可以控制強制刷新snapshots,但是不可以刷新releases,下面是-U參數的說明:
 
-U,--update-snapshots                  Forces a check for missing
                                        releases and updated snapshots on
                                        remote repositories
 
 
由於我們build的release會自動安裝(install)到服務器的.m2目錄,所以在該服務器上build其他的jar包會成功(假設jenkins是分佈式而非單機,這樣操作就會失敗了)。
 
以前我們設置的release服務器不允許Re-deploy,重複提交RELEASE版本會導致失敗,這也是控制RELEASE意外被修改的一種辦法。
 
 
 
 
 
 
 
  • 38e24d5f-51f4-35a8-b53e-3bb9f68e7c75-thumb.png
  • 大小: 82.6 KB
  • f3ccaf1f-1ef8-3236-97e0-c723d2417478-thumb.png
  • 大小: 18.6 KB
  • 20b04e89-1d81-30ad-93e3-97066281b4cd-thumb.png
  • 大小: 27.2 KB
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章