1、Maven介紹
Maven 翻譯為"專家"、"內行",是 Apache 下的一個純 Java 開發的開源項目。基於項目對象模型(縮寫:POM)概念,Maven利用一個中央信息片斷能管理一個項目的構建、報告和文檔等步驟。
Maven是一個管理工具,可以對 Java 項目進行構建、依賴管理。Maven 曾是 Jakarta 項目的子項目,現為由 Apache 軟件基金會主持的獨立 Apache 項目,
2、Maven特點
- 項目設置遵循統一的規則
- 任意工程中共享
- 依賴管理包括自動更新
- 一個龐大且不斷增長的庫
- 可擴展,能夠輕松編寫 Java 或腳本語言的插件
- 只需很少或不需要額外配置即可即時訪問新功能
- 基於模型的構建 − Maven能夠將任意數量的項目構建到預定義的輸出類型中,如 JAR,WAR 或基於項目元數據的分發,而不需要在大多數情況下執行任何腳本
- 項目信息的一致性站點 − 使用與構建過程相同的元數據,Maven 能夠生成一個網站或PDF,包括您要添加的任何文檔,並添加到關於項目開發狀態的標准報告中
- 發布管理和發布單獨的輸出 − Maven 將不需要額外的配置,就可以與源代碼管理系統(如 Subversion 或 Git)集成,並可以基於某個標簽管理項目的發布。也可以發布到分發位置供其他項目使用。包含其他依賴和文檔的歸檔,或者作為源代碼發布。
- 向后兼容性 − 您可以很輕松的從舊版本 Maven 的多個模塊移植到 Maven 3 中
- 子項目使用父項目依賴時,正常情況子項目應該繼承父項目依賴,無需使用版本號
3、Maven scope依賴范圍詳解
Maven的生命周期存在編譯、測試、運行這些過程,那么顯然有些依賴只用於測試,比如junit;有些依賴編譯用不到,只有運行的時候才能用到,比如mysql的驅動包在編譯期就用不到(編譯期用的是JDBC接口),而是在運行時用到的;還有些依賴,編譯期要用到,而運行期不需要提供,因為有些容器已經提供了,比如servlet-api在tomcat中已經提供了,我們只需要的是編譯期提供而已。總結說來,在POM 4中,<dependency>中還引入了<scope>,它主要管理依賴的部署。大致有compile、provided、runtime、test、system等幾個。
- compile:默認的scope,運行期有效,需要打入包中
- provided:編譯期有效,運行期不需要提供,不會打入包中
- runtime:編譯不需要,在運行期有效,需要導入包中。(接口與實現分離)
- test:測試需要,不會打入包中
- system:非本地倉庫引入、存在系統的某個路徑下的jar。(一般不使用)
3.1 compile模式(編譯范圍)
默認就是compile,什么都不配置也就是意味着compile。compile表示被依賴項目需要參與當前項目的編譯,當然后續的測試,運行周期也參與其中,是一個比較強的依賴。打包的時候通常需要包含進去.
該依賴需要參與當前項目的編譯、測試、運行、打包
3.2 compile模式(運行時范圍)
runntime表示被依賴項目無需參與項目的編譯,不過后期的測試和運行周期需要其參與。與compile相比,跳過編譯而已.
比如,你可能在編譯的時候只需要JDBC API JAR,而只有在運行的時候才需要JDBC驅動實現。
編譯時該包不參與,運行時參與
3.3 test 模式(測試范圍)
test范圍依賴 在一般的編譯和運行時都不需要,它們只有在測試編譯和測試運行階段可用。比如
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <scope>test</scope> </dependency>
3.4 provided(已提供范圍)
provided 表明該依賴已經提供,故只在未提供時才被使用,
應用場景是你定義了一個Servlet,此刻得需要Servlet-api.jar 才能編譯成功,但是當你達成war 包時,你並不想將 Servlet-api.jar 包進去,因為Tomcat等容器會提供
跟compile 類似,說明JDK、容器或使用者會提供這個依賴,如Servlet.jar
這個依賴只作用在** 編譯和測試,該依賴會由系統組件提供,不需手動添加,只存在編譯、運行、測試階段,打包是不用包進去,打包階段做了exclude**動作
provided意味着打包的時候可以不用包進去,別的設施(Web Container)會提供。
阿里開發規范文檔:如果依賴其它二方庫,盡量是 provided 引入,讓二方庫使用者去依賴具體版本號; 無 log 具體實現,只依賴日志框架
例如 : 添加<scope>provided</scope>,因為provided表明該包只在編譯和測試的時候用,所以,當啟動tomcat的時候,就不會沖突了
<dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>3.0-alpha-1</version> <scope>provided</scope> </dependency>
3.5 system (系統范圍)
被依賴項不會從maven倉庫下載,而是從本地系統指定路徑下尋找,需要 systemPath 屬性
system范圍依賴與provided 類似,但是你必須顯式的提供一個對於本地系統中JAR 文件的路徑,這么做是為了允許基於本地對象編譯,而這些對象是系統類庫的一部分。這樣的構件應該是一直可用的,Maven 也不會在倉庫中去尋找它
從參與度來說,與provided相同,不過被依賴項不會從maven倉庫抓,而是從本地文件系統拿,一定需要配合systemPath屬性使用,例如:
一、方式1.dependency 本地jar包,如果沒有建私服,可以在pom.xml中通過文件方式引
<dependency> <!--自定義--> <groupId>com.im</groupId> <!--自定義--> <artifactId>sdk</artifactId> <!--自定義--> <version>1.0</version> <!--system,類似provided,需要顯式提供依賴的jar以后,Maven就不會在Repository中查找它--> <scope>system</scope> <!--項目根目錄下的lib文件夾下--> <systemPath>${basedir}/lib/sdk-1.0.jar</systemPath> </dependency>
二、方式2.編譯階段指定外部lib
<plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> <compilerArguments> <!--指定外部lib--> <extdirs>lib</extdirs> </compilerArguments> </configuration> </plugin>
三、方式3.0 將外部jar打入本地maven倉庫
mvn install:install-file -Dfile=sdk-1.0.jar -DgroupId=com.im -DartifactId=sdk -Dversion=1.0 -Dpackaging=jar
四、方式3.1 引入jar包
<dependency> <groupId>com.im</groupId> <artifactId>sdk</artifactId> <version>1.0</version> </dependency>
五、maven預定義內置屬性
${basedir}表示項目根目錄,即包含pom.xml文件的目錄; ${version}表示項目版本; ${project.basedir}同${basedir}; ${project.baseUri}表示項目文件地址; ${maven.build.timestamp}表示項目構件開始時間; ${maven.build.timestamp.format}表示屬性${maven.build.timestamp}的展示格式,默認值為yyyyMMdd-HHmm,可自定義其格式
4、scope 的傳遞依賴
A -> B -> C, 當前項目 A,A依賴於B,B依賴於C,知道B在 A中的scope,怎么知道 C在 A 中的 scope
即,A需不需要 C的問題,本質由 C在B中的scope決定
當 C 在 B 中的scope 是test 或 provided 時,C 直接被丟棄,A不依賴C
否則 A 依賴 C,C的scope 繼承與B 的scope