目錄java
Maven
,Ant
,Gradle
都是項目管理構建工具;apache
的一個頗爲成功的開源項目,maven
主要服務於Java
平臺的項目構建、依賴管理、項目信息管理// 查看版本 mvn -v // 清除target(項目生成的字節碼文件) mvn clean // 編譯項目 .java 文件轉換爲.class文件 mvn compile // 測試,測試以前已經進行了 mvn compile // 測試的類必須以Test結尾 mvn test // 打包項目 mvn package // 安裝jar包到項目中 mvn install
<dependency> <groupId>com.zhao.MQTT</groupId> // 包名通常是公司的網址 + 項目名稱 <artifactId>MQTT-Login</artifactId>// 通常是項目名稱 + 模塊功能名稱 <version>1.0-SNAPSHOT</version> // 版本 <type>.....</type> // 依賴的類型,對應於項目座標定義的packageing,大部分狀況下不用申明,默認是jar <scope>....</scope>// 依賴的範圍 <optional>...</optional> // 標記依賴是否可選 <exclusions> // 排除傳遞性依賴 <exclusion> ...... </exclusion> </exclusions> </dependency>
依賴範圍就是用來控制依賴與三種classpath(編譯classpath、測試classpath、運行classpath)的關係,maven有如下幾種依賴範圍:mysql
編譯依賴範圍。 若是沒有指定,就會默認使用該依賴範圍。使用此依賴範圍的maven依賴,對於編譯,測試,運行三種classpath都有效。典型的例子就是spring-core,在編譯、測試和運行的時候都須要使用該依賴
測試依賴範圍。 使用次依賴範圍的maven依賴,只對於測試classpath有效,在編譯主代碼或者運行項目的使用時將沒法使用此類依賴。典型的例子就是JUnit,它只有在編譯測試代碼及運行測試的時候裁須要
已提供依賴範圍。 使用次依賴範圍的maven依賴,只對於編譯和測試classpath有效,可是運行時無效。
運行時依賴範圍。 對於測試和運行classpath有效,可是在編譯主代碼時無效。典型的例子就是JDBC驅動的實現,項目主代碼的編譯只須要JDK提供的JDBC接口,只有在執行測試或者運行項目的時候裁須要實現上述接口的具體JDBC驅動。
A依賴於B,B依賴於C,那麼C就是A的一個傳遞性依賴;spring
依賴範圍不只能夠用來控制依賴和三種classpath的關係,並且還對傳遞性依賴產生影響。sql
假設A依賴於B,B依賴於C,那麼咱們說A對於B是第一直接依賴,B對於C是第二直接依賴,A對於C是傳遞性依賴。第一直接依賴的範圍和第二直接依賴的範圍決定了傳遞性依賴的範圍數據庫
maven引入的傳遞性依賴機制,一方面大大簡化和方便了依賴申明,另外一方面,大部分狀況下咱們只須要關心項目的直接依賴是什麼,而不是考慮這些直接依賴會引入什麼傳遞性依賴。可是有時候,當傳遞性依賴形成問題的時候,咱們就須要清除的知道該傳遞性依賴是從那條依賴路徑引入的。apache
項目A有這樣的例子:A->B->C->X(1.0),A->D->X(2.0),X是A的傳遞性依賴,可是兩個依賴路徑上有兩個版本的X,那麼那個X會被maven解析使用呢?
兩個版本的依賴都被解析顯然是不對的,由於那樣的話會形成依賴重複,所以必須選擇一個。api
mavne的依賴調解機制的第一原則不能解決全部的問題,好比這樣的依賴關係:
A->B->Y(1.0),A->C->Y(2.0),依賴路徑都是2,那麼到底誰會被解析使用呢?在maven以前的版本中,這是不肯定的,可是在maven2.0.9版本後,爲了儘量的避免構建的不肯定性,maven定義了依賴的調解的第二原則:第一申明者優先,在依賴長度相等的狀況下,在pom
表中依賴生命的順序決定了誰會被解析使用。順序最靠前的那個依賴優勝。例子中:若是B的依賴申明在C以前,那麼Y(1.0)就會被解析使用。緩存
項目A依賴於項目B,項目B依賴於項目X和Y,B對於X和Y的依賴都是可選依賴:A->B、B->X(可選),B->Y(可選)。根據依賴性傳遞的定義,若是這個三個依賴的範圍都是compile,那麼X和Y就是A的compile範圍傳遞性依賴。安全
可是這裏的X、Y是可選依賴了,依賴將不會得以傳遞。換句話說:X,Y將不會對A有任何影響。springboot
好比B是一個持久層隔離工具包,它支持多種數據庫,包括mysql,oracle,在構建的時候須要這兩種數據庫的驅動,可是在使用這個工具包的時候,只須要某一個驅動;
實際的應用中,咱們應該儘量的避免可選依賴的出現
傳遞性依賴會給項目隱式地引入不少依賴,這極大地假話了項目依賴的管理,可是有些時候這種特性也會帶來問題,例如當前鮮蘑菇中有一個第三方依賴,而這個依賴因爲某些緣由依賴了另一個類庫的snapashot,那麼這個snapshot就會成爲當前項目的傳遞性依賴,而snpshot的不穩定性會直接影響到當前的項目。
有些時候你也可能想替換掉某個傳遞性依賴,換成本身想要的依賴。好比 sun jta api,hiberanate依賴與這個jar,可是因爲版權的因素,該類庫不在中央倉庫中,而apache geronimo項目有一個對應的實現,這時候咱們就能夠排除sun jat api,申明Geronimo的jta api實現。
不少關於spring framework的依賴,它們分別是org.springframework:spring-core:2.5.六、org.springframework:spring-context-support:2.5.6,它們都是來自同一個項目的不一樣模塊。所以浙西惡意來的版本都是相同的,並且是能夠預見的,若是未來升級spring framework,這些依賴的版本會一塊兒升級。
以下
<properties> <spring.version>4.3.9.RELEASE</spring.version> </properties> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency>
對於mavne來講:倉庫只分爲兩類:本地倉庫和遠程倉庫。當maven根據左邊尋找構建的時候,首先回去本地倉庫,若是沒有回去中央倉庫,下載到本地,而後使用。
如何修改本地倉庫地址?
<localRepository>/path/to/local/repo</localRepository>// 修改本地倉庫的地址
每一個用戶只有一個本地倉庫,可是能夠訪問配置多個遠程倉庫
私服是一種特殊的遠程倉庫,是架設在局域網內部的倉庫,私服代理廣域網上的遠程倉庫,工局域網內的maven用戶使用。當maven須要下載構建的時候,它從私服請求,若是私服上不存在該構建,則從外部的遠程倉庫下載。緩存在私服上以後,在爲maven的下載請求提供服務。
一些沒法從外部倉庫下載到的構建也能從本地上傳到私服上供咱們使用
不少狀況下,默認的中央倉庫沒法知足項目的需求,可能項目須要的構建存在於另外一個遠程倉庫中,如JBoss Maven倉庫中,這時,能夠在pom表中配置該倉庫,請注意實在pom表中
<repositories> <repository> <id>juziwl</id> <name>Juzi Repository</name> <url>http://192.168.129.198:8081/nexus/content/groups/public </url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories>
大部分的遠程倉庫無需認證就能夠訪問,可是有時候處於安全方面的考慮,咱們須要提供認證信息才能訪問一些遠程倉庫。
例如:組織內部有一個maven倉庫服務器,該服務器爲每一個項目都提供獨立的maven倉庫,爲了防止非法的倉庫訪問,管理員爲每一個倉庫提供了一組用戶名及密碼。這時候爲了能讓maven訪問倉庫內容,就須要配置認證信息。
配置認證信息和配置倉庫信息不一樣,倉庫信息能夠直接配置在pom文件中,可是認證信息必須配置在settings.xml文件中。由於pom每每是被提交到代碼倉庫中共全部成員訪問的,而settings.xml通常只放在本機。所以在settings.xml中配置認證信息更爲安全。
<servers> <server> <id>juziwl3</id> <username>admin</username> <password>admin123</password> </server> </servers>
這裏面的id很關鍵,必須和pom表中須要認證的repository元素的id徹底一致。換句話說,正是這個id降認證信息與倉庫配置聯繫在了一塊兒。
私服的最大用處就是部署第三方構建,包括組織內部生成的構建以及一些沒法從外部倉庫直接獲取的構建,不管是平常開發中生成的構建,仍是正式版本發佈的構建,都須要部署到倉庫中供其餘團隊成員使用。
maven除了能對項目進行編譯、測試、打包以外,還能夠將項目生成的構建部署到倉庫中。須要在pom.xml中進行配置。
<distributionManagement> <repository> <id>juziwl</id> <name>Juzi Repository</name> <url>http://192.168.129.198:8081/nexus/content/groups/public</url> </repository> <distributionManagement> <snapshotRepository> <id>juziwl</id> <name>Juzi SnapshotRepository</name> <url>http://192.168.129.198:8081/nexus/content/groups/public</url> </snapshotRepository> </distributionManagement> </distributionManagement>
distributionManagement包含repository和snapshotRepository子元素,前者表示發佈版本構件的倉庫,後者表示快照版本的倉庫。
往遠程倉庫部署構建的時候認證的。配置須要在settings.xml進行配置
<servers> <server> <id>juziwl3</id> <username>admin</username> <password>admin123</password> </server> </servers>
而後命令行:
mvn clean deploy
若是項目的當前的版本是快照版本,則部署到快照版本倉庫地址,不然就部署到發佈版本倉庫地址。
若是倉庫X能夠提供倉庫Y存儲的全部內容,那麼就能夠認爲X是Y的一個鏡像,換句話說,任何一個能夠從倉庫Y獲取的構建均可以從X獲取。
settings.xml配置文件
<mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors>
例子中:
關於鏡像的一個更爲常見的用法就是結合私服。因爲私服能夠代理任何外部的公共倉庫(包括中央倉庫),所以,對於組織內部的maven用戶來講,使用給一個私服地址就等於使用了全部須要的外部倉庫,這能夠將配置集中到私服,從而簡化maven自己的配置,在這種狀況下,任何須要的構建均可以從私服獲取,私服就是全部倉庫的鏡像。
<mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>*</mirrorOf> </mirror> </mirrors>
該例子中:
在maven中存在三套生命週期,每一套生命週期都是相互獨立的,互不影響
cleanLifeCycle:清理的生命週期 clean defaultLifeCycle:默認的生命週期 compile,test,package,install,deploy siteLifeCycle:站點生命週期 site
之因此說是三套生命週期,是由於他們之間互不影響;
可是在一套生命週期以內執行後面的命令前面操做會自動執行;
從命令執行mavne任務的最主要方式就是調用maven的生命週期階段。須要注意的是,各個生命週期是相互獨立的,而一個生命週期的階段四有先後依賴關係的。
maven的核心僅僅定義了抽象的生命週期,具體的任務是交由插件完成的,插件以獨立的構建形式存在。
maven的生命週期與插件相互綁定,用以完成實際的構建任務。具體而言,是生命週期的階段與插件的目標相互綁定,以完成某個具體的構建任務。例如項目編譯這一任務,它對應了default生命週期的compile這一階段,而maven-compile-plugin這一插件的compile目標可以完成該任務。所以將他們綁定,就能實現項目編譯的目的。
完成了插件和生命週期的綁定以後,用戶還能夠配置插件目標的參數,進一步調整插件目標所執行的任務,以知足項目的需求。幾乎全部的maven插件的目標都有一些可配置的參數,用戶能夠經過命令行和pom配置等方式來配置這些參數。
不少插件目標的參數都支持從命令行配置,用戶能夠在manve命令中使用-D參數,病伴隨一個參數=參數值形式,來配置插件目標的參數。
例如:maven-surefire-plugin提供一個maven.test.skip的參數,當其值爲true的時候,就會跳過執行測試。因而,在運行命令的時候,加上以下:
mvn install -Dmaven.test.skip=true
-D是java自帶的,其功能就是經過命令行設置一個java系統屬性,maven簡單的重用了改參數,在準備插件的時候檢查系統屬性,便實現了插件參數的配置。
並非全部的插件參數都適合從命令行配置,有些參數的值從項目建立的發哦項目發佈都不會改變,或者說不多改變,對於這種狀況,在POM文件中一次性配置就顯然比重複在命令行輸入要方便。
用戶能夠在申明插件的時候,對此插件進行一個全局的配置。也就是說,全部該基於該插件目標的任務,都會使用這些配置。例如,咱們一般會須要配置maven-compiler-plugin 告訴它編譯Java1.5版本的源文件,生成與JVM1.5兼容的字節碼文件。
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
Maven聚合(或者稱爲多模塊),是爲了可以使用一條命令就構建多個模塊,例如已經有兩個模塊,分別爲account-email,account-persist,咱們須要建立一個額外的模塊(假設名字爲account-aggregator,而後經過該模塊,來構建整個項目的全部模塊,accout-aggregator自己做爲一個Maven項目,它必須有本身的POM,不過做爲一個聚合項目,其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>demo</groupId> <artifactId>demo</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>demo-springboot</module> <module>demo-java</module> <module>demo-provider</module> <module>demo-consumer</module> <module>demo-generator</module> </modules> </project>
上面有一個特殊的地方就是