Maven[?mev?n]能幫你構(gòu)建工程蚁廓,管理jar包,編譯代碼厨幻,還能幫你自動運(yùn)行單元測試相嵌,打包腿时,生成報表,甚至能幫你部署項目饭宾,生成Web站點(diǎn)批糟, 為開發(fā)者提供了一套完整的構(gòu)建生命周期框架。開發(fā)團(tuán)隊幾乎不用花多少時間就能夠自動完成工程的基礎(chǔ)構(gòu)建配置看铆,因為 Maven 使用了一個標(biāo)準(zhǔn)的目錄結(jié)構(gòu)和一個默認(rèn)的構(gòu)建生命周期徽鼎。
1. POM文件
Maven 工程結(jié)構(gòu)和內(nèi)容被定義在一個 xml 文件中 pom.xml
,是 Project Object Model (POM) 的簡稱弹惦,此文件是整個 Maven 系統(tǒng)的基礎(chǔ)組件否淤。POM 它放在工程根目錄下,包含了關(guān)于工程和各種配置細(xì)節(jié)的信息棠隐,Maven 使用這些信息構(gòu)建工程石抡。也包含了目標(biāo)和插件。當(dāng)執(zhí)行一個任務(wù)或者目標(biāo)時助泽,Maven 會查找當(dāng)前目錄下的 POM啰扛,從其中讀取所需要的配置信息,然后執(zhí)行目標(biāo)嗡贺。下面是一個簡單的pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<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>Hust</groupId>
<artifactId>Gongmei</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>Gongmei Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<lucene.version>6.0.1</lucene.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!--<scope>provided</scope>-->
</dependency>
</dependencies>
<build>
<!--解決IDEA自動重置LanguageLevel和JavaCompiler版本的問題-->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
<finalName>cloud</finalName>
</build>
</project>
POM文件的要求
- 每個工程應(yīng)該只有一個 POM 文件隐解。
- 所有的 POM 文件需要 project 元素和三個必須的字段:groupId, artifactId,version。表達(dá)當(dāng)前工程的信息
- 在倉庫中的工程標(biāo)識為 groupId:artifactId:version
節(jié)點(diǎn) | 說明 |
---|---|
groupID | 這是工程組的標(biāo)識暑刃。它在一個組織或者項目中通常是唯一的厢漩。例如,一個銀行組織 com.company.bank 擁有所有的和銀行相關(guān)的項目岩臣。 |
artifactId | 這是工程的標(biāo)識溜嗜。它通常是工程的名稱。例如架谎,消費(fèi)者銀行炸宵。groupId 和 artifactId 一起定義了 artifact 在倉庫中的位置。 |
version | 這是工程的版本號谷扣。在 artifact 的倉庫中土全,它用來區(qū)分不同的版本。例如:com.company.bank:consumer-banking:1.0 com.company.bank:consumer-banking:1.1. |
properties | 項目中的配置文件会涎。指明項目中一些配置裹匙,例如字體編碼以及版本號等 |
dependencies | 項目中的依賴文件爽撒。即項目中需要引入的jar包换淆。 |
plugins | maven插件辙浑。Maven 實(shí)際上是一個依賴插件執(zhí)行的框架腻异,每個任務(wù)實(shí)際上是由插件完成话浇。Build plugins:在構(gòu)建時執(zhí)行煎楣;Reporting plugins:在網(wǎng)站生成過程中執(zhí)行 |
2. Maven構(gòu)建聲明周期
三個關(guān)鍵字:
- lifecycle 生命周期
- phase 階段
- goal 目標(biāo)
lifecycle 中包含phase 砂吞,phase 中包含goal 预茄。
2.1 lifestyle
每個lifecycle 中都包含一個或多個phase 。通過 Maven 命令調(diào)用lifecycle中的phase時项鬼,該lifecycle中phase之前以及包括該phase在內(nèi)的所有phase會被執(zhí)行哑梳。Maven 有以下三個默認(rèn)的生命周期:
- clean 刪除構(gòu)建目錄
- build 構(gòu)建應(yīng)用
- site 創(chuàng)建新的報告文檔、部署站點(diǎn)
2.2 phase
執(zhí)行phase實(shí)際執(zhí)行的是goal绘盟。如果一個phase沒有綁定goal鸠真,這個phase就不會被執(zhí)行。每個phase定義了一個或多個goals 奥此,其中的goals是順序執(zhí)行弧哎。一些phase默認(rèn)已經(jīng)綁定了一些goal。對于default lifecycle來說稚虎, 這些被綁定的goal并不完全相同撤嫩,而是和packaging value相關(guān)。
2.3 goal
最終被執(zhí)行的就是goal蠢终,goal與goal之間是獨(dú)立的序攘。因此單獨(dú)執(zhí)行一個goal不會導(dǎo)致其他goal被執(zhí)行。
e.g: mvn clean dependency:copy-dependencies package
,maven會順序執(zhí)行這3個對象中包含的所有g(shù)oal寻拂。
3. Maven倉庫
Maven倉庫有三種類型:
- 本地(local)
- 中央(central)
- 遠(yuǎn)程(remote)
3.1 本地倉庫
Maven 本地倉庫保存你的工程的所有依賴(library jar程奠、plugin jar 等)。當(dāng)你運(yùn)行一次 Maven 構(gòu)建祭钉,Maven 會自動從中央庫或遠(yuǎn)程庫下載所有依賴的 jar 文件到本地倉庫中瞄沙。它避免了每次構(gòu)建時都引用存放在遠(yuǎn)程機(jī)器上的依賴文件。
Maven 本地倉庫默認(rèn)被創(chuàng)建在 %USER_HOME% 目錄下慌核。要修改默認(rèn)位置距境,在 %M2_HOME%\conf 目錄中的 Maven 的 settings.xml 文件中定義另一個路徑。
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>C:/MyLocalRepository</localRepository>
</settings>
3.2 中央倉庫
Maven 中央倉庫是由 Maven 社區(qū)提供的倉庫垮卓,其中包含了大量常用的庫垫桂。通俗一點(diǎn)說,就是一個網(wǎng)站粟按,上面存放大量的庫诬滩,項目中用到中央倉庫的相關(guān)文件,就自動下載下來灭将√勰瘢可以在maven文件夾下的settings.xml中更改中央倉庫的地址
<!-- mirror
| Specifies a repository mirror site to use instead of a given repository. The repository that
| this mirror serves has an ID that matches the mirrorOf element of this mi rror. IDs are used
| for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
|
<mirror>
<id>mirrorId</id>
<mirrorOf>repositoryId</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://my.repository.com/repo/path</url>
</mirror>
-->
3.3 遠(yuǎn)程倉庫
如果 Maven 在中央倉庫中也找不到依賴的庫文件,它會停止構(gòu)建過程并輸出錯誤信息到控制臺庙曙】站担可以在pom文件中指定遠(yuǎn)程倉庫地址,那么Maven就會從該遠(yuǎn)程倉庫下載依賴:
<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.companyname.projectgroup</groupId>
<artifactId>project</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>com.companyname.common-lib</groupId>
<artifactId>common-lib</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>companyname.lib1</id>
<url>http://download.companyname.org/maven2/lib1</url>
</repository>
<repository>
<id>companyname.lib2</id>
<url>http://download.companyname.org/maven2/lib2</url>
</repository>
</repositories>
</project>
3.4 Maven依賴搜索順序
步驟 1 - 在本地倉庫中搜索,如果找不到姑裂,執(zhí)行步驟 2,如果找到了則執(zhí)行其他操作男旗。
步驟 2 - 在中央倉庫中搜索舶斧,如果找不到,并且有一個或多個遠(yuǎn)程倉庫已經(jīng)設(shè)置察皇,則執(zhí)行步驟 4茴厉,如果找到了則下載到本地倉庫中。
步驟 3 - 如果遠(yuǎn)程倉庫沒有被設(shè)置什荣,Maven 將簡單的停滯處理并拋出錯誤(無法找到依賴的文件)矾缓。
步驟 4 - 在一個或多個遠(yuǎn)程倉庫中搜索依賴的文件,如果找到則下載到本地倉庫已被將來引用稻爬,否則 Maven 將停止處理并拋出錯誤(無法找到依賴的文件)
4. Maven插件
另外一種將goal綁定到phase的方法就是在project中使用plugin嗜闻,一個plugin可能有一個或多個goal,其中每個goal代表一個plugin的功能桅锄。
4.1 插件的使用
一琉雳、插件通常提供了一個目標(biāo)的集合,可以使用下面的方法使用:
mvn [plugin-name]:[goal-name]
例如友瘤,一個 Java 工程可以使用 maven-compiler plugin 的 compile (goal) 編譯翠肘,使用以下命令:
mvn compiler:compile
4.2 常用的插件列表
插件 | 說明 |
---|---|
clean | 構(gòu)建之后清理目標(biāo)文件(target文件),刪除目標(biāo)目錄 |
compiler | 編譯Java源文件 |
surefile | 運(yùn)行junit單元測試辫秧,創(chuàng)建測試報告 |
jar | 從當(dāng)前工程中構(gòu)建jar文件 |
war | 從當(dāng)前工程中構(gòu)建war文件 |
javadoc | 為工程生成javadoc |
antrun | 從構(gòu)建過程的任意一個階段中運(yùn)行一個ant任務(wù)的集合 |
5. Maven打包的詳細(xì)過程
mvn clean package
執(zhí)行詳細(xì)過程如下:
從圖中我們可以看到Maven的執(zhí)行順序:
1束倍、使用清理插件:maven-clean-plugin:2.5執(zhí)行清理刪除已有target目錄(版本2.5)
2、使用資源插件:maven-resources-plugin:2.6執(zhí)行資源文件的處理(版本2.6)
3盟戏、使用編譯插件:maven-compiler-plugin:3.1編譯所有源文件生成class文件至target\classes目錄下(版本3.1)
4绪妹、使用資源插件:maven-resources-plugin:2.6:testResource執(zhí)行測試資源文件的處理(版本2.6)
5、使用編譯插件:maven-compiler-plugin:3.1:testCompile編譯測試目錄下的所有源代碼(版本3.1)
6抓半、使用插件:maven-surefire-plugin:2.12.4運(yùn)行測試用例(版本2.12.4)喂急;
7、使用插件:maven-jar-plugin:2.4對編譯后生成的文件進(jìn)行打包笛求,包名稱默認(rèn)為:artifactId-version廊移,比如本例生成的jar文件:Gongmei-1.0-SNAPSHOT,包文件保存在target目錄下探入,將該war包放入tomcat目錄下的webapp中運(yùn)行即可狡孔。
備注:不管是compile、package還是install等前三個步驟都是必不可少的蜂嗽,即清理已有目錄苗膝,處理資源文件、編譯源文件植旧。
6. Maven常用插件
maven默認(rèn)會依據(jù)項目類型自動把構(gòu)建時的各階段(Lifecycle和phase)自動綁定到特定插件提供的功能(goal)點(diǎn)上辱揭。例如java項目編譯(compile)階段,實(shí)際上是調(diào)用了maven-compiler-plugin插件提供的compile功能點(diǎn)來實(shí)現(xiàn)的离唐。
- maven-resources-plugin 文件資源配置
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding> <!--配置資源文件編碼-->
</configuration>
</plugin>
-
maven-compiler-plugin 編譯配置
默認(rèn)綁定到compile phase。maven2默認(rèn)使用的是jdk5问窃,jdk版本一般自己指定亥鬓。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding> <!--指定utf-8版本-->
<compilerArgument>-Xlint:none</compilerArgument>
<compilerArguments>
<extdirs>libs</extdirs> <!--使用項目中的jar包-->
</compilerArguments>
</configuration>
</plugin>
-
maven-surefire-plugin 單元測試
默認(rèn)綁定到test階段
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore> <!--測試有失敗用例時,是否繼續(xù)構(gòu)建-->
<skipTests>true</skipTests> <!--是否跳過測試階段域庇,方式1-->
<skip>true</skip> <!--是否跳過測試階段嵌戈,方式2-->
</configuration>
</plugin>
-
maven-jar-plugin 打jar包
普通java項目(非web項目或其它類型的特殊項目),package階段默認(rèn)綁定的插件听皿,能夠?qū)⒕幾g好的class和資源達(dá)成jar包,但不包含依賴
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<excludes> <!--打包時要排除的文件-->
<exclude>agent.properties</exclude>
</excludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!-- <classpathPrefix>lib/</classpathPrefix> -->
<mainClass>com.demo.HelloWorld</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
-
maven-assembly-plugin 打包含依賴的全包
在打包時熟呛,對jar包的打包形式進(jìn)行自定義配置
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptors>
<!--自定義配置文件-->
<descriptor>src/main/resources/package.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
下面是具體的配置package.xml
<assembly>
<id>bin</id>
<!-- 最終打包成一個用于發(fā)布的zip文件 -->
<formats>
<format>zip</format>
</formats>
- maven-war-plugin 打war包
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<warName>${project.artifactId}</warName>
<webResources>
<resource> <!--將額外的jar依賴打入war包-->
<directory>libs/</directory>
<targetPath>WEB-INF/lib</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
</webResources>
<packagingExcludes>css/**,html/**</packagingExcludes>
</configuration>
</plugin>
- maven-source-plugin 打包源碼
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>