看到一份2018 年 JVM 生態報告提到,使用構建工具的比例,maven高達60%,遠高於gradle的19%。
我平常也使用maven,於是就整理了一些maven的常用知識。
關於maven的博文已經浩如煙海 ,所以這裏我只是總結一些自己常用知識,以做備忘。
倉庫
分爲本地倉庫和遠程倉庫
遠程倉庫默認使用的是 Maven 社區提供的中央倉庫
還有其他社區提供的倉庫,如jcenter,jboss。
一般公司都會使用Nexus部署一個私服(也是倉庫),用於存放公司內部構件。
mvn deploy 可以將項目生成的構件分發到私服。
鏡像
因爲中央倉庫一般部署在外國,下載構件速度比較慢,所以可以通過鏡像mirror下載, mirrorOf配置代理倉庫。
當需要從代理倉庫下載構件時,都會轉爲從鏡像下載。
鏡像中不存在該構件時,鏡像會從倉庫下載,緩存到鏡像中。
需要注意的是,由於鏡像完全屏蔽了代理倉庫,當鏡像不穩定或者停止服務的時候,Maven不會直接訪問代理倉庫,因而將無法下載構件。
最常用的是阿里提供的鏡像服務:
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
profile
profile用於定義不同環境的不同配置,如開發,測試環境使用不同的倉庫,打包方式等。
mvn clean package -Ppro即構建出pro環境需要的war包
構造
構造Java項目mvn archetype:generate -DinteractiveMode=false -DgroupId=com.binecy -DartifactId=my-core
構造Web項目mvn archetype:generate -DinteractiveMode=false -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=com.binecy -DartifactId=my-web
構造子模塊
構造父模塊# mvn archetype:generate -DinteractiveMode=false -DgroupId=com.binecy -DartifactId=system-core
進入system-core項目# cd system-core
刪除不需要的src文件夾# rm src
修改pom.xml文件,將<packaging>jar</packaging>修改爲<packaging>pom</packaging>
構造子模塊system-dao# mvn archetype:generate -DinteractiveMode=false -DgroupId=com.binecy -DartifactId=system-dao
構造子模塊system-web# mvn archetype:generate -DinteractiveMode=false -DgroupId=com.binecy -DartifactId=system-web
這時父模塊的pom.xml已經自動添加了module信息
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.binecy</groupId>
<artifactId>system-core</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>system-core</name>
<url>http://maven.apache.org</url>
<modules>
<module>system-service</module>
<module>system-web</module>
</modules>
</project>
一個多模塊的項目構造完成。
dependencyManagement
父模塊中定義的dependencies,子模塊默認繼承,不需重複定義也可以使用。
父模塊中定義的dependencyManagement只是聲明依賴,並不實現引入,如果子模塊也定義了該依賴,可以繼承父模塊dependencyManagement中定義的version和scope,不用需要聲明這兩個屬性。
如果子模塊也聲明瞭version屬性,則使用子模塊聲明的版本。
跳過測試mvn install -Dmaven.test.skip=true
使用tomcat插件
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
<port>9090</port>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
依賴衝突
依賴傳遞
如果我們的項目A依賴構件B,而構件B又依賴於構件C,依賴的關係爲:A—>B—>C
當我們執行項目A,maven會下載構件B,構件C
依賴衝突
如果有一下依賴關係
A—>B—>C(version:0.0.1)
A—>D>—C(version:0.0.2)
那麼項目A引入哪個版本的構件C呢?
這裏有兩個重要的依賴調解原則。
1:如果依賴路徑的長度不同,則“短路優先”:
A—>B—>C—>D—>E—>X(version 0.0.1)
A—>F—>X(version 0.0.2)
則A依賴於X(version 0.0.2)。
2:依賴路徑長度相同情況下,則“先聲明優先”:
A—>E—>X(version 0.0.1)
A—>F—>X(version 0.0.2)
如果項目A的depencies先聲明引入E,這A依賴於X(version 0.0.1)
依賴衝突,通常是低版本的依賴覆蓋了高版本的依賴,而某些構件使用了高版本特有的功能導致的。這時可以使用dependency:tree分析依賴關係,使用exclusions排除重複的依賴或者添加優化級更高的正確依賴。
參考:
Maven 核心原理