《Maven實戰》筆記
maven是什麽
maven是
- 構建工具
- 依賴關系工具
- 項目信息管理工具
而JAVA世界的ant只是一個構建工具,不具備依賴管理的功能,需要配合使用ivy進行依賴管理。
maven的安裝
下載maven,配置環境變量。
升級的技巧:使用符號鏈接,環境變量指向符號鏈接,升級的時候修改符號鏈接即可。
maven使用入門
手動搭建maven項目
- 編寫pom
- 編寫主代碼和測試代碼
使用ArcheType創建maven項目骨架
命令如下mvn archetype:generate
實際上上述命令的完整格式是:mvn groupId:artifactId:version:goal
即運行的是archetype插件的generate目標。
也可以為自己的項目開發archetype。
編譯,測試,打包,安裝,運行
- 編譯:
mvn clean compile
- 測試:
mvn clean test
- 打包:
mvn clean package
- 安裝:
mvn clean install
- 運行
- 使用maven-shade-plugin插件生成可執行的jar.
- pom中配置shade插件。
- 執行
mvn clean install
,重新生成jar包。
- 運行jar包。
java -jar xxx.jar
- 使用maven-shade-plugin插件生成可執行的jar.
坐標和依賴
maven坐標的各個元素
- groupId
- artifactId
- version
- packaging:打包方式。比如jar或者war。
- classifier:附屬構件。比如javadoc和源代碼。
依賴的元素
- groupId
- artifactId
- version
- type:同坐標中的packaging。默認為jar。
- scope:依賴範圍
- optional
- exclusions
依賴範圍
三種classpath:編譯classpath,測試classpath,運行classpath。
- compile:對編譯、測試、運行三種classpath都有效。
- test:只對測試classpath有效。比如JUnit。
- provided:編譯和測試classpath有效,運行classpath無效。比如servlet API。
- runtime:測試和運行classpath有效,編譯classpath無效。比如JDBC驅動實現。
- system:與provided一致。只是這種情況必須顯示指定依賴文件的路徑,這樣就和本機系統綁定了,使得構建不具有移植性,慎用。
- import:不會對三種classpath產生影響。
依賴範圍不僅可以控制依賴與三種classpath的關系,還對傳遞性依賴產生影響。
傳遞性依賴
傳遞性依賴機制:maven會解析各個直接依賴的pom,將那些必要的間接依賴以傳遞性依賴的形式引入到當前項目中。(我們只需要關心項目的直接依賴)
maven會自動解析所有項目的直接依賴和傳遞性依賴,確保每個構件只有唯一的版本在依賴中存在。最後解析後的這些依賴被稱為已解析依賴
。
相關命令
查看已解析依賴:mvn dependency:list
依賴樹:mvn dependency:tree
分析依賴:mvn dependency:analyze
生命周期和插件
生命周期和階段
maven對構建過程進行了抽象,被稱為生命周期
。生命周期本身不做具體任務,實際的任務由插件
完成。這是一種模板方法模式。
生命周期包含一些階段
(phase),這些階段有前後依賴關系,後面的階段依賴前面的階段。可以定義多個生命周期,生命周期之間彼此是獨立的,不存在依賴關系。
Maven擁有三套獨立的生命周期,分別是clean、default和site。
- clean生命周期的目的是清理項目。
- default生命周期的目的是構建項目。
- site生命周期的目的是建立項目站點。
clean生命周期
包含三個階段:
- pre-clean
- clean
- post-clean
defalut生命周期
包含的階段太多,詳情 Introduction to the Build Lifecycle。
site生命周期
- pre-site
- site
- post-site
- site-deploy
命令行與生命周期的關系
常用的mvn clean compile
命令實際上調用的是clean生命周期的clean階段和default生命周期的compile階段。
插件和插件目標
對於插件而言,為了能夠復用代碼,它能夠執行多個任務,實現多個功能,這些功能聚集在一個插件裏,每個功能就是一個插件目標
。比如maven-dependency-plugin插件,它可以分析項目依賴,列出項目的依賴樹,找出無用依賴。
通常寫法是:插件:插件目標
。
插件綁定
將生命周期中的階段和插件目標綁定。
那麽在命令行輸入生命周期的階段,則對應的插件目標就會執行相應的任務。
Q:是否可以直接在命令行中直接指定執行某個插件目標‘???
A:可以。
多個插件目標可以綁定到同一個階段。
總結
A Build Lifecycle is Made Up of Phases
A Build Phase is Made Up of Plugin Goals
聚合和繼承
聚合
解決如下需求:想要用一條命令一次性構建多個項目(模塊)。
這就是maven聚合(多模塊)特性。
方法:增加一個聚合模塊,其中的pom.xml中的packaging為pom。
聚合模塊和其他模塊的目錄關系
不一定是父子關系,也可以是平行的目錄結構。
繼承
目的:解決多模塊maven項目的配置重復問題。
方法:增加一個父模塊,在父pom中聲明一些配置供子pom繼承。
父模塊和聚合模塊一般同時存在多模塊maven項目中。父模塊也要在聚合模塊中的modules標簽中配置。
可繼承的pom元素
- groupId
- version
- dependencies
- dependencyManagement
- build
- repositories
- properties
- ...
依賴管理
可以將一些依賴放到父模塊的dependencies元素中,這樣子類就無需配置了。但會存在一個問題:所有的子模塊都會依賴父模塊dependencies元素中聲明的依賴,即使一些子模塊並不需要這些依賴。
解決方法:
在父模塊中使用dependencyManagement元素聲明依賴,這些依賴不為直接被子模塊繼承。子模塊若要繼承父模塊dependencyManagement中聲明的某個依賴的話,則需要在子模塊中的dependencies元素中重新聲明(只需要配置groupId和artifactId即可)。
雖然這種方式不會大幅度的減少配置,但是由於在父模塊的pom中統一申明了依賴的版本,可以避免在子模塊中使用的依賴版本不一致的情況。
import依賴範圍
名為import的依賴範圍只在dependencyManagement元素下采用效果。其作用是將目標pom中的dependencyManagement配置導入並合並到當前pom中的dependencyManagement元素中。
插件管理
pluginManagement和dependencyManagement類似。
聚合與繼承的關系
目的不同:
- 聚合是為了方便快速構建項目。
- 繼承是為了消除重復配置。
聚合模塊 vs. 被聚合模塊:聚合模塊知道被聚合模塊,但被聚合模塊不知道聚合模塊的存在。
父模塊 vs. 子模塊:父模塊不知道那些子模塊繼承自它,但子模塊都知道自己的父模塊。
相同點:父模塊和聚合模塊都沒有實際內容,並且兩者的pom中的packaging都必須是pom。
實際項目中,會發現一個pom既是父pom,又是聚合pom,這麽做主要是為了方便。
約定優於配置
所有的pom都繼承自超級POM。
對於Maven3,超級POM在$MAVEN_HOME/lib/maven-model-builder-x.x.x.jar中的org/apache/maven/model/pom-4.0.0.xml路徑下。
對於Maven2,超級POM在$MAVEN_HOME/lib/maven-model-x.x.x-uber.jar中的org/apache/maven/pom-4.0.0.xml路徑下。
在超級POM中已經定義了源代碼的路徑、構建的輸出路徑等信息。
反應堆
構建一個多模塊項目時,由於模塊間存在繼承或者聚合關系,模塊間的構建是有先後關系的,整體構成一個有向無環圖DAG。反應堆就是所有模塊組成的一個構建結構。
持續集成
比如TensorFlow的持續集成:http://ci.tensorflow.org/
使用maven構建web應用
war文件的目錄結構
todo
web項目的maven目錄結構
todo
快速生成web項目的maven目錄結構
生成web項目的maven目錄結構
jetty-maven-plugin插件
doc
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.13.v20130916</version>
<configuration>
<webApp>
<contextPath>/</contextPath>
</webApp>
<connectors>
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<port>8081</port>
<maxIdleTime>60000</maxIdleTime>
</connector>
</connectors>
</configuration>
</plugin>
http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin
使用cargo實現自動化部署
Cargo支持兩種本地部署的方式:standalone模式和existing模式。如下是standalone模式:
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.6.2</version>
<configuration>
<container>
<containerId>tomcat8x</containerId>
<home>D:\Program Files\apache-tomcat-8.0.23</home>
</container>
<configuration>
<type>standalone</type>
<home>${project.build.directory}/tomcat8x</home>
<properties>
<cargo.servlet.port>8181</cargo.servlet.port>
</properties>
</configuration>
</configuration>
</plugin>
existing模式:
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.6.2</version>
<configuration>
<container>
<containerId>tomcat8x</containerId>
<home>D:\Program Files\apache-tomcat-8.0.23</home>
</container>
<configuration>
<type>existing</type>
<home>D:\Program Files\apache-tomcat-8.0.23</home>
<!-- existing模式下好像無法更改端口 -->
<!--<properties>-->
<!--<cargo.servlet.port>8080</cargo.servlet.port>-->
<!--</properties>-->
</configuration>
</configuration>
</plugin>
Archetype
Archetype Catalog
- internal:maven-archetype-plugin內置的Archetype Catalog。
- local:~/.m2/archetype-catalog.xml
- remote:http://repo1.maven.org/maven2/archetype-catalog.xml https://repo.maven.apache.org/maven2/archetype-catalog.xml
- file://...:本機任何位置上的archetype-catalog.xml文件。
- http://...:使用http協議指定遠程的archetype-catalog.xml文件。
mvn archetype:generate
卡住的問題
原因:
執行命令mvn archetype:generate
時,maven-archetype-plugin插件會先尋找archetype-catalog.xml文件,默認是從中央庫中尋找該文件。由於中央庫訪問比較慢,所以出現卡頓現象。
解決方案:
-
方案(1):加上archetypeCatalog參數
mvn archetype:generate -DarchetypeCatalog=internal
-
方案(2):配置一個國內的鏡像,加速對archetype-catalog.xml的訪問。比如阿裏雲的maven鏡像,如下:
<mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror>
經驗:安裝maven後一定要配置一個國內的中央庫鏡像,比如阿裏maven中央鏡像庫。因為後續很多mvn命令需要下載很多插件和依賴,網絡不好容易導致操作失敗。
阿裏雲maven庫列表
下載單個構建的源碼和文檔
mvn dependency:get -Dartifact=com.alibaba.citrus:citrus-webx-all:3.2.4:jar:sources
mvn dependency:get -Dartifact=com.alibaba.citrus:citrus-webx-all:3.2.4:jar:javadoc
《Maven實戰》筆記