maven入門
http://maven.apache.org/guides/index.html
Maven 能夠幫助開發者完成以下工作:
構建
文檔生成
報告
依賴
SCMs
發佈
分發
郵件列表
總的來說,Maven 簡化了工程的構建過程,並對其標準化。它無縫銜接了編譯、發佈、文檔生成、團隊合作和其他任務。Maven 提高了重用性,負責了大部分構建相關的任務。
Maven 3.3 要求 JDK 1.7 或以上
Maven 3.2 要求 JDK 1.6 或以上
Maven 3.0/3.1 要求 JDK 1.5 或以上
安裝
#mac
tar xzvf apache-maven-3.5.0-bin.tar.gz 或
unzip apache-maven-3.5.0-bin.zip
mv apache-maven-3.5.0 ~/Programs/
vi ~/.bash_profile
// <MAVEN-DIR>爲你的安裝目錄---------
export PATH=$PATH:<MAVEN-DIR>/bin
// 然後source 一下profile文件,檢查是否安裝成功
source ~/.bash_profile
mvn -version
vi ~/.m2/settings.xml
#windows
先安裝jdk
解壓到個目錄
將bin子目錄加入到path環境變量
在命令行上mvn -v 測試
簡單使用
#交互方式創建項目目錄結構
mvn archetype:generate
981: remote -> org.apache.maven.archetypes:maven-archetype-quickstart (-)
選擇一個版本 6--1.1
選擇groupId,artifactId,version,package
#非交互方式創建
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
mvn -B archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DgroupId=com.mycompany.app \
-DartifactId=my-app
以上命令是使用org.apache.maven.plugins:maven-archetype-plugin:3.0.1:generate創建的
可參考https://maven.apache.org/archetype/maven-archetype-plugin/generate-mojo.html
#編譯
命令行進入到pom.xml文件的目錄
mvn compile
使java 編譯器來編譯項目,可以在pom.xml中指定相關jdk版本
編譯好的代碼在${basedir}/target/classes目錄
#編譯測試源碼並進行單元測試
Test Driven Development(TDD)
mvn test
#只編譯測試代碼
mvn test-compile
#生成jar
mvn package
生成的jar 在 ${basedir}/target
#安裝到${user.home}/.m2/repository
mvn install
surefire plugin 會按照名字尋找test類
**/*Test.java
**/Test*.java
**/*TestCase.java
默認會排除
**/Abstract*Test.java
**/Abstract*TestCase.java
#關於junit
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
#運行
cd my-app
java -cp target/my-app-1.0-SNAPSHOT.jar com.mycompany.app.App
mvn clean dependency:copy-dependencies package
#生成site
mvn site
#清理
mvn clean
會刪除target 目錄
#生成idea 項目
mvn idea:idea
#生成eclipse項目
mvn eclipse:eclipse
eclipse 中一般默認已經安裝好m2eclipse 插件
http://www.eclipse.org/m2e/
#其他
mvn jar:jar
不會重新編譯源代碼,僅會從target/classes目錄創建一個jar
#SNAPSHOT
SNAPSHOT是開發分支的最新代碼,並不保證它是stable或者unchanging. 而release 或沒有SNAPSHOT後綴的代碼表示不會改變了。
換句話說對於x.y-SNAPSHOT 變成x.y 就是release,而新的開發版本應該是x.(y+1)-SNAPSHOT.
plugin
想要定製化build,可以通過添加plugins來完成
以下的例子表示源文件的版本是5.0的,生成的class文件的版本也是5.0的
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
maven中的plugin看起來像是a dependency, 它會自動下載並被使用。如果不指定version默認是使用最新版
comfiguration元素應用到compiler plugin的每一個goal.
plugin 列表
http://maven.apache.org/plugins/
配置plugin的說明
http://maven.apache.org/guides/mini/guide-configuring-plugins.html
將resources添加到jar
要使用標準目錄結構
http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
src/main/java
src/main/resources
src/main/webapp
src/test/java
src/test/resources
src/it
LICENSE.TXT
NOTICE.TXT
README.TXT
resources中的文件,目錄結構會以同樣的結構自動加入到jar的根目錄
|-- META-INF
| |-- MANIFEST.MF
| |-- application.properties
| `-- maven
| `-- com.mycompany.app
| `-- my-app
| |-- pom.properties
| `-- pom.xml
`-- com
`-- mycompany
`-- app
`-- App.class
下面是pom.properties的內容
version=1.0-SNAPSHOT
groupId=com.jamie
m2e.projectName=test101
m2e.projectLocation=/Users/jamie/Documents/mavenworkspace/test101
artifactId=test101
http://maven.apache.org/guides/getting-started/index.html
filter resource & properties
有時我們需要一個值才build時才知道。這時在resource file中使用${property name>},而這個property 在pom.xml,settings.xml,在外部的properties file,或者a system property
爲了使maven在複製時可以filter resources,設置filtering的值爲true 在pom.xml的resource目錄
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
在resource 文件中引用時如${project.name},${project.version},
${project.build.finalName}
${settings.localRepository}
例如:放在src/main/resources目錄中的資源application.properties文件中
有一些佔位符
#application.properties
application.name=${project.name}
application.version=${project.version}
在process-resources phase 會copy 並且filter 資源文件
mvn process-resources
這個過程之後,在target/classes 目錄下的application.properties文件會看起來這樣
#application.properties
application.name=Maven Quick Start Archetype
application.version=1.0-SNAPSHOT
如果屬性定義在外部的文件中,要放在src/main/filters 目錄下,比如叫做filter.properties
#filter.properties
my.filter.value=hello!
現在可以pom.xml中加入這個文件的位置
<build>
<filters>
<filter>src/main/filters/filter.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
# application.properties
application.name=${project.name}
application.version=${project.version}
message=${my.filter.value}
執行mvn process-resources可以看到target/classes/application.properties中的佔位符被替換爲filter.properties中的值
properties的定義除了可以放在filter.properties中,也可以放在pom文件的properties section
<properties>
<my.filter.value>hello</my.filter.value>
</properties>
filtering resouces 也可以從system properties中獲得值,如java中的java.version,
user.home 或者在mvn的命令行中用了-D 參數的
mvn process-resources "-Dcommand.line.prop=hello again"
使用外部依賴
完整介紹 http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
dependency節點有4個屬性groupId,artifactId,version,scope
scope的值可以是compile,test,runtime
maven先從local repository(${user.home}/.m2/repository中尋到依賴;如果local repository中不存在,maven會從remote repository中下載到local repository, 默認的remote repository是http://repo.maven.apache.org/maven2/ 可以建立自己的maven私服
可以參考
http://maven.apache.org/guides/introduction/introduction-to-repositories.html
通過google搜索site:www.ibiblio.org maven2 log4j 可以獲知log4j的歷史版本及最新版本
在mvn compile 階段完成下載
佈署jar到remote repository
在pom.xml中配置那個遠程repository的相關信息,如authenticaiton information.
下面的例子是使用scp 和username/password authentication
pom.xml
<distributionManagement>
<repository>
<id>mycompany-repository</id>
<name>MyCompany Repository</name>
<url>scp://repository.mycompany.com/repository/maven2</url>
</repository>
</distributionManagement>
settings.xml
<servers>
<server>
<id>mycompany-repository</id>
<username>jvanzyl</username>
<!-- Default value is ~/.ssh/id_dsa -->
<privateKey>/path/to/identity</privateKey> (default is ~/.ssh/id_dsa)
<passphrase>my_key_passphrase</passphrase>
</server>
</servers>
或
<server>
<id>mycompany-nexus-releases</id>
<username>deployment</username>
<password>12345678</password>
</server>
<server>
<id>mycompany-nexus-snapshots</id>
<username>deployment</username>
<password>12345678</password>
</server>
更多請參考
http://maven.apache.org/guides/mini/guide-encryption.html
創建其他類型的項目
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=com.mycompany.app -DartifactId=my-webapp
會創建大約如下的pom.xml
<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-webapp</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>my-webapp</finalName>
</build>
</project>
mvn clean package
會看到target/my-webapp.war文件創建了
如何一次build多個project
目錄結構
+- pom.xml
+- my-app
| +- pom.xml
| +- src
| +- main
| +- java
+- my-webapp
| +- pom.xml
| +- src
| +- main
| +- webapp
父pom
<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>app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>my-app</module>
<module>my-webapp</module>
</modules>
</project>
webapp依賴於my-app生成的一個jar 所以my-webapp/pom.xml 如下
<dependencies>
<dependency>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
...
</dependencies>
在每個子項目的pom.xml中加入parent節點
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>app</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
然後在 父目錄下
mvn clean install
WAR會被創建在my-webapp/target/my-webapp.war ,其中包含了jar
$ jar tvf my-webapp/target/my-webapp-1.0-SNAPSHOT.war
0 Fri Jun 24 10:59:56 EST 2005 META-INF/
222 Fri Jun 24 10:59:54 EST 2005 META-INF/MANIFEST.MF
0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/
0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/
0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/
3239 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.xml
0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/
215 Fri Jun 24 10:59:56 EST 2005 WEB-INF/web.xml
123 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.properties
52 Fri Jun 24 10:59:56 EST 2005 index.jsp
0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/
2713 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/my-app-1.0-SNAPSHOT.jar
如何做到的? 首先,父pom的packaging值爲pom,並含有一些modules,這告訴maven在所有的子模塊中運行相關命令而不僅僅是父模塊。(更改這種行爲可以在命令行中加入--non-recursive)
然後,我們告訴war 依賴於my-app生成的jar,這做了如下的事情:把生成的jar放在war項目的classpath中以便War中的代碼可以調用,確保jar總是在war前build,並指示war plugin把jar包含在它的library 目錄中
你可能注意到junit-4.11.jar在依賴中,但是war中並沒有。原因是它在<scope>test</scope>中,它僅用在testing,所以沒有像有<compile> scope的my-app一樣被加入到war中
最後一步是在子模塊中包含一個parent 節點,這與maven 1.0中的extend 元素不是,parent 元素確保了pom總會被定位,即使在repository中尋找時the project相對於父模塊是各自分離的
不同於maven 1.0, 並不要求先運行mvn install, 你可以只是運行mvn package,被依賴的包會從target directories被找到,而不是從local repository
(Unlike Maven 1.0, it is not required that you run install to successfully perform these steps - you can run package on its own and the artifacts in the reactor will be used from the target directories instead of the local repository.)