創建project
先去官方網站下載一個最新版本http://maven.apache.org/download.cgi. 下載後解壓,使用之前最好先將maven的bin目錄設置到path環境變量裏面。
maven無非也就是用來build一個project的,直接先上一個例子,在命令行下輸入下面的命令:
mvn archetype:generate DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.mycompany.app -DartifactId=myapp
mvn就是maven的命令行程序,archetype:generate中的archetype是plugin的名字,generate是goal的名字,命令行後面的是一些參數。關於archetype和goal以及後面的參數,後面再細說。
如果是第一次運行,這個過程會有點慢,maven需要下載一些依賴項,中間如果有輸入提示信息,直接回車使用默認值就可以了。這條命令執行完後,會在你的當前目錄下生成一個名爲myapp的目錄:
注意這個目錄結構,src/main/java 和 src/test/java 是不能改動,不然maven會無法找到源文件。下面是maven一個標準的目錄結構:
src/main/java |
Application/Library sources |
src/main/resources |
Application/Library resources |
src/main/filters |
Resource filter files |
src/main/assembly |
Assembly descriptors |
src/main/config |
Configuration files |
src/main/scripts |
Application/Library scripts |
src/main/webapp |
Web application sources |
src/test/java |
Test sources |
src/test/resources |
Test resources |
src/test/filters |
Test resource filter files |
src/site |
Site |
Maven提倡使用一個共同的標準目錄結構,使開發人員能在熟悉了一個Maven工程後,對其他的Maven工程也能清晰瞭解。這樣做也省去了很多設置的麻煩。
以上的文檔介紹是Maven希望的目錄結構,並且也是目錄創建工程是採用的目錄結構。Maven推薦大家儘可能的遵守這樣的目錄結構。
在頂級目錄上是工程的描述文件pom.xml(如果使用Ant則還包括其他屬性文件,maven.xml或build.xml),另外還包括提供給最終用戶的文件,如,README.txt,LICENSE.txt等等。
頂級目錄還包括兩個子目錄:src,target。頂級目錄下可能出現的其他目錄僅僅是CVS或.svn和其他多模塊工程的工程目錄,最好不要再有其他目錄。
Target目錄是所有工程編譯構建的輸出目錄。
Src目錄包含所有工程的源碼文件,配置文件,資源文件等等。它下面的子目錄一般包含main(主要的工程源文件),test(測試文件),site(項目站點文件)。
標準目錄結構:
src
-main
–bin 腳本庫
–java java源代碼文件
–resources 資源庫,會自動複製到classes目錄裏
–filters 資源過濾文件
–assembly 組件的描述配置(如何打包)
–config 配置文件
–webapp web應用的目錄。WEB-INF、css、js等
-test
–java 單元測試java源代碼文件
–resources 測試需要用的資源庫
–filters 測試資源過濾庫
-site Site(一些文檔)
target
LICENSE.txt Project’s license
README.txt Project’s readme
工程根目錄下就只有src和target兩個目錄
target是有存放項目構建後的文件和目錄,jar包、war包、編譯的class文件等。
target裏的所有內容都是maven構建的時候生成的
maven默認生成了一個重要的文件pom.xml,maven就是通過這個文件來來管理整個project,可以理解位類似於eclipse的.project文件。默認生成的pom.xml文件的內容如下:
/* 1-1 */
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.1.0.1</version>
<packaging>jar</packaging>
<name>myapp</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
解釋一下這個xml文件的內容:
- modelVersion: 這個XML文件所使用的POM格式的版本
- groupId: 相當於這個project的所有者或者機構的一個標識,一般是com.company.xxx這種格式
- artifactId: 這個project最後所生成的文檔(jar、war)的名字,比如對於junit這個開源的project,它的artifactId就是junit
- packaging: 這個project的打包的類型,一般是war、jar等值
- version: project的版本
- name: project的名字,生成文檔等內容的時候會用的這個名字
這個project創建好後和普通的project沒有什麼不同,我們直接往裏面放源代碼進行開發就可以了,如果有目錄想修改的也完全可以。
POM & archetype
archetype就是一個project的模板,上面我們生成的project就是用默認的archetype生成的。如果使用不同的archetype,生成的project結構會有所不同。 一個archetype指明瞭
- 1) 項目的目錄結構以及什麼目錄是放source code,哪些是放test source code,哪些目錄是放resource的。
- 2) 一個默認的pom.xml文件,這個默認的pom.xml文件中的groupId,artifactId,version用佔位符表示,在創建project的時候通過參數傳進來。
pom.xml文件的POM全稱是Project Object Model,這個文件對於maven的使用者來說是一個和maven交互的渠道,pom.xml包含了一個maven project的配置,一個project該如何編譯打包,project有哪些依賴項等等。
仔細看一下我們前面創建project的命令:mvn archetype:generate DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.mycompany.app -DartifactId=myapp
- 1) archetype:generate, 這是一個maven的plugin,用來從一個archetype創建一個project,關於plugin後面再說。
- 2) DarchetypeGroupId,這個就是指的archetype的groupid,也就是說是用的哪個archetype,或者說用哪個項目模板。
- 3) 後面的兩個參數,用來放大pom.xml文件裏面,作爲當前創建的project的描述信息。
Project創建好了,看如何去編譯,直接進入的project的目錄,在命令行下:
mvn compile
編譯完後maven會創建一個target目錄去保存編譯結果。 我們需要編譯成一個什麼樣的內容,以及要輸出到什麼地方等等,都是可以在pom.xml文件裏面配置的,但是因爲我們目前並沒有指定這些內容,所以maven會使用默認值。
我們還可以用maven執行test:
mvn test
第一次執行時,maven會去下載一些依賴項。另外要注意的時,如果我們更改了默認的目錄結構,maven會因爲找bu到test而無法去執行test。如果只需要編譯test可以執行:
mvn test-compile
要把項目打包,執行:
mvn package
mvn會根據pom.xml裏面的packaging選項打包成相應的文件。
repository & dependency
maven裏面有一個repository的概念,當我們的項目依賴於某個jar時,maven會去repository裏面去找。repository分兩種,一種是遠程的,一種是本地的。如果有幾個project都用到junit,我們可以把junit放在repository裏面,幾個project可以公用,節約存儲空間而且方便管理,這個repository的位置可以在pom.xml裏面設置。
本地的默認的路徑是安裝用戶的目錄下的 .m2\repository 文件夾。如果一個依賴項在本地的repository裏面沒有,那麼maven會去他自己的遠程的repositoryhttp://repo.maven.apache.org/maven2 去下載後放到本地的repository裏面。
也就是說,我們如果我們的project需要要引用一個依賴項,我們只需要在pom.xml文件中進行配置,maven會自動幫我們去引用。 我們之前的創建project裏面需要寫單元測試,引用到了junit,看pom中的配置:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
每一個需要爲每一個 dependency 指明groupId,artifactId,version。scope很簡單,意思是說我們需要怎麼引用,比如我們上面的例子裏面設置的是test,意思是說只在test裏面引用junit。 但是我們如何知道groupId,artifactId和version呢? 比如我現在想引用log4j,這個幾個值怎麼填? 可以去http://mirrors.ibiblio.org/maven2/ 上去查找。比如log4j,我們就在上面這個地址加上log4j,也就是http://mirrors.ibiblio.org/maven2/junit/。進去後會有一個maven-metadata.xml,打開就可以知道這些值瞭然後添加這個dependency了。
如果要把一個project安裝到本地的repository裏面,可以執行下面的命令:
mvn install
到這裏就說完了創建,編譯,測試,打包以及安裝,大部分的項目也就是做這些事情。
再介紹幾個其它命令:
- mvn site : 爲你的project創建一個站點
- mvn clean: 清除target目錄下的所有文件
- mvn eclipse:eclipse :爲project生成eclipse的工程文件和classpath文件
build lifecycle & build phase & goal
maven有一套build的生命週期,是按照一套順序走下來的,這一套順序就叫一個生命週期(lifecycle)。maven內置三種生命週期:default, clean 和 site。一個生命週期分爲多個build phase,下面是default生命週期全部的build phase:
- validate:validate the project is correct and all necessary information is available.
- initialize:initialize build state, e.g. set properties or create directories.
- generate-sources:generate any source code for inclusion in compilation.
- process-sources:process the source code, for example to filter any values.
- generate-resources:generate resources for inclusion in the package.
- process-resources:copy and process the resources into the destination directory, ready for packaging.
- compile:compile the source code of the project.
- process-classes:post-process the generated files from compilation, for example to do bytecode enhancement on Java classes.
- generate-test-sources:generate any test source code for inclusion in compilation.
- process-test-sources:process the test source code, for example to filter any values.
- generate-test-resources:create resources for testing.
- process-test-resources:copy and process the resources into the test destination directory.
- test-compile:compile the test source code into the test destination directory
- process-test-classes:post-process the generated files from test compilation, for example to do bytecode enhancement on Java classes. For Maven 2.0.5 and above.
- test:run tests using a suitable unit testing framework. These tests should not require the code be packaged or deployed.
- prepare-package:perform any operations necessary to prepare a package before the actual packaging. This often results in an unpacked, processed version of the package. (Maven 2.1 and above)
- package:take the compiled code and package it in its distributable format, such as a JAR.
- pre-integration-test:perform actions required before integration tests are executed. This may involve things such as setting up the required environment.
- integration-test:process and deploy the package if necessary into an environment where integration tests can be run.
- post-integration-test:perform actions required after integration tests have been executed. This may including cleaning up the environment.
- verify:run any checks to verify the package is valid and meets quality criteria.
- install:install the package into the local repository, for use as a dependency in other projects locally.
- deploy:done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects.
這些build phase是按照順序執行的,如果執行後面的build phase,前面的build phase 也會被執行。例如如果執行:
mvn deploy
前面的install、verify一直到validate這些build phase都會執行。
每一個build phase是由goal組成的,一個goal其實就是一個任務,一個goal可以關聯到一個build phase也可以不關聯到任何build phase 。 不關聯到任何phase的goal是可以獨立執行的,例如:
mvn clean dependency:copy-dependencies package
上面的命令會導致先執行clean這個phase,然後拷貝依賴項,最後打包。注意,這裏clean這個goal是clean這個lifecycle裏面的一個goal,所以可以看到不同lifecycle的build phase和goal是可以混合在一起執行的。 如果一個goal被綁定到多個phase上,那麼goal就會被執行多次。
phase的順序是已經固定的,如果一個phase沒有綁定到任何goal,那麼phase就不會被執行。 一個goal可以通過兩種方式綁定到一個phase,一個是指定packaging,另一個就是plugin。
packaging&plugin
plugin就是用來向maven提供goal的。一個plugin裏面可以有多個goal,這就是爲什麼我們在指明goal時,前面會用一個冒號與plugin的名字。
一個plugin自己可以指定自己的goal綁定到哪個lifecycle的哪一個Phase上,另外也可以配置一個goal綁定到哪個phase上。可以在pom.xml裏面配置。 看兩個配置:
<plugin>
<groupId>org.codehaus.modello</groupId>
<artifactId>modello-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<configuration>
<models>
<model>src/main/mdo/maven.mdo</model>
</models>
<version>4.0.0</version>
</configuration>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
</plugin>
這個就在當前的lifecycle裏面添加了一個名字叫java的goal,這goal會根據自己的配置去綁定到一個phase,在phase執行的時候這個goal會執行。並且在這個配置裏面,可以指定多個execution來讓這個goal執行多次。
看另一個示例配置:
<plugin>
<groupId>com.mycompany.example</groupId>
<artifactId>display-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>process-test-resources</phase>
<goals>
<goal>time</goal>
</goals>
</execution>
</executions>
</plugin>
這個名爲time的goal把自己綁定到了process-test-resource這個phase上。
在默認情況下,並不是所有的phase都綁定了goal,比如clean這個lifecycle是有三個phase的,但是隻有其中的一個名爲clean的phase默認綁定了一個clean:clean goal,其它兩個phase默認沒有綁定任何goal。
之前已經提到過packaging,在pom.xml可以指定packaging,每種packaging都設定了一組phase和goal之間的綁定關係。在default lifecycle下,當packaging爲 ejb/ejb3/jar/par/rar/war 其中之一的值的時候,只有以下的phase綁定了goal,具體如下:
process-resources |
resources:resources |
compile |
compiler:compile |
process-test-resources |
resources:testResources |
test-compile |
compiler:testCompile |
test |
surefire:test |
package |
jar:jar |
install |
install:install |
deploy |
deploy:deploy |
總結
首先搞清楚maven的project的目錄結構,然後理解maven的lifecycle,lifecycle是由build phase組成,每一個build phase會綁定到goal。goal是由plugin提供的。 每一種packaging的值都表明了一定的phase和goal之間的綁定關係。
另外一個很重要的就是dependency,我們要在項目中引用一個依賴,只需要在pom.xml指定依賴的名字和版本,maven會自動去遠程的repository下載,然後放到本地的repository裏面,這樣以後所有的project都可以共用
其它細節可以參考http://maven.apache.org/guides/index.html。