首發日期:2018-11-04
Maven的介紹:
什么是Maven:
- Maven是apache旗下的一個java開源項目。
- Maven是一個項目管理工具,它可以幫助我們管理項目
- 可以使用Maven對java項目進行項目構建(構建包括清理、編譯、測試、報告、打包、部署六個過程,你可以認為是一個項目的從代碼到完整可運行項目的過程)、依賴管理。
為什么要學習maven?
以一個例子說一下maven的好處,說了它的好處,
1.maven可以幫我們管理依賴。在以往的時候,我們都是手動的導入jar包,然后build path;在導入jar包之前,我們需要去查找有哪些包,需要哪些包,這是一個非常繁雜的問題,如果你不是“老司機”的話,你可能會遺漏某些jar包;而在maven中,我們可以使用pom.xml來聲明需要哪些依賴包,然后maven就會根據pom.xml中的信息去獲取倉庫中的依賴包的引用,這就相當於導入了jar包。而且,maven存儲了大量的jar包和大量的依賴規則,所以你可以直接去百度搜索一下某個關鍵字+maven
,就可以查找到某個框架或工具的依賴信息,直接把這個依賴信息拷貝到pom.xml中,maven就會幫你管理這個依賴。
2.maven可以幫我們進行工程管理。在以往的時候,我們開發一個項目都是在一個工程中開發,但事實上這對多人開發並不友好,多個開發者之間的開發產生了耦合關系,這對整合造成了一些小困擾(但並不是說不好,只是說有更好的手段)。而使用maven之后,可以建立多個工程來組成一個項目,在不同的工程中開發不同的模塊,而多個工程之間的關系由maven管理,maven可以幫我們把多個工程組合成一個項目。
安裝與配置:
下載:
點擊鏈接,下載Maven:
下載完了之后,直接解壓即可,它是免安裝的。
配置環境變量
-
配置
JAVA_HOME
環境變量,值是jdk程序根目錄【如果已經配置過的,可以省略】 -
將
%JAVA_HOME%\bin
添加到path環境變量中【如果已經配置過的,可以省略】【注意不要弄亂了path的值】 -
配置
MAVEN_HOME
環境變量,值是maven程序根目錄 -
將
%MAVEN_HOME%\bin
添加到path環境變量中【注意不要弄亂了path的值】
測試安裝結果:
配置了環境變量后,可以在CMD中鍵入mvn -v
來測試是否可以運行,下面是我的輸出結果:
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-18T02:33:14+08:00)
Maven home: J:\software\apache-maven-3.5.4\bin\..
Java version: 1.8.0_91, vendor: Oracle Corporation, runtime: E:\SOFTWARD\Java\jdk1.8.0_91\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
Maven概念:
在學會maven之前,先了解幾個概念。下面的概念了解即可,后面會在實際的配置中涉及。
坐標
在以往的build path過程中,其實只是把jar包的路徑引用添加到eclipse中,eclipse知道需要的包的路徑之后,在編譯的時候會去引用。
而maven可以根據坐標來指定使用哪個依賴包,坐標經過一定的組合規則就可以得出依賴包所在的路徑,maven會根據坐標對應的路徑在倉庫中來查找jar包。
-
maven用三個向量來組成一個坐標,這個坐標確定唯一的依賴包:
- groupid:公司或組織域名倒序+項目名
- artifactid:模塊名\工程名
- version:jar包版本
-
maven會根據坐標在倉庫中來查找jar包,把三個向量拼接起來就是依賴包的路徑。
-
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.0.RELEASE</version> </dependency> <!--對應的路徑轉換格式:groupid/artifactid/artifactid+version+.jar --> <!--org/springframework/spring-core/spring-core4.3.0.RELEASE .jar-->
-
倉庫
在上面提到了坐標,你應該認識到了坐標標識了依賴包的路徑,而這個路徑是相對於倉庫的路徑的。為什么需要一個倉庫呢?上面說了eclipse實質上也是通過路徑來導入依賴包的,如果你沒有一個統一的文件夾來管理依賴包的話,零散的依賴包足以讓你頭疼了。而maven的倉庫是一個包含了眾多依賴包的倉庫,而且maven的依賴管理可以很方便地添加依賴包信息。
- 倉庫的分類
- 本地倉庫:本機上的倉庫,通常都會有一個本機倉庫,不然你老是需要從遠程倉庫獲取的話就很費時間了;而事實上maven會指定一個默認的本地倉庫路徑,第一次使用maven的時候,會把maven需要的插件和遠程庫中存儲的jar包下載下來並存儲到本地倉庫中。
- 遠程倉庫:事實上你可以給本地倉庫存儲你自己的jar包,而某個jar包本地沒有的時候,就需要從遠程倉庫下載下來。
- 私服倉庫:是一個遠程倉庫,但距離比較近,通常是企業中自己內部的maven倉庫,通常私服maven倉庫都會使用nexus來搭建。
- 中央倉庫:是maven維護的遠程倉庫,它里面存儲的東西比較全。
- 依賴包的查找順序:先從本地倉庫查找,本地倉庫沒有就去遠程倉庫查找(企業中一般是本地倉庫->私服倉庫->中央倉庫)。當查找到了之后,都會下載到本地倉庫。【記住初始情況下,maven的倉庫是比較干凈的,僅僅包含一些基本插件。】
- 倉庫中存儲的內容:
- 插件【maven的功能依賴於插件,沒有插件就沒有功能,好比電腦需要驅動,maven的構建是通過插件來實現的】
- jar包
- 自己開發的maven工程【其實你應該知道自己是可以把自己的工程打成jar包,然后可以在別的工程中導入這個jar包來使用這個jar包中的類,所以你是可以把自己的類庫放到倉庫中的】
入門示例
下面以創建一個maven項目,並使用maven的依賴管理來給項目添加依賴為例:
創建maven工程:
關於如何創建一個maven項目,下面以eclipse中的為例,如果你需要idea的,可以點擊下面的鏈接學習。
圖解在IntelliJ IDEA中創建第一個Maven項目
新建工程->選擇maven project
添加依賴
在pom.xml中添加下列代碼:
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
可以看得出來,依賴已經導入了我們項目的類庫。
所以我們利用依賴包中的類來編寫代碼的時候就不會報錯了。
Maven標准目錄結構
maven要依據一定的目錄規范來管理項目,所以要想用maven管理項目,要遵循規范。下面會講一下目錄定義規范,這樣是面向全手動創建maven項目的時候,在很多時候,都會使用工具來創建,比如eclipse中就可以直接創建一個maven工程,這個工程遵循maven工程的目錄規范。
約定的目錄結構
maven構建一個工程要遵循這個目錄規范。
- 工程目錄【下面的縮進程度代表目錄級數】
- src目錄:存放工程源碼的地方
- main目錄:存放主程序的源代碼,這里放的是主體程序代碼。
- java目錄:存放java源文件
- resource目錄:存放框架或其他工具的配置文件
- 【為web項目時會多出一個webapp目錄】webapp目錄:存放頁面素材
- test目錄:存放測試程序的源代碼的地方,這里放的都是一些測試用的代碼。
- java目錄:存放java源文件
- resource目錄:存放框架或其他工具的配置文件
- main目錄:存放主程序的源代碼,這里放的是主體程序代碼。
- pom.xml文件:這個文件定義了這個maven工程的相關配置。
- src目錄:存放工程源碼的地方
補充:
- maven使用一個pom.xml文件來管理依賴。pom中配置依賴信息和maven的一些配置信息,這會在下面講解。
pom配置:
- pom是Project Object Model項目對象模型的意思。
- pom.xml是maven工程的核心文件,與構建工程相關的一切配置(依賴信息、插件信息等等)都在這個文件中配置
- pom.xml中的可配置標簽很多,我們這里僅僅介紹經常使用的。這些經常使用的也足夠你日常使用了。
常見標簽
- modelVersion:是pom的版本,一般都是默認生成的,不需要關心
- groupId:標識當前工程的所屬組織,寫法類似包名。【為什么工程也有這個呢?因為我們的工程也是能打包到本地倉庫的。】
- artifactId:當前工程的工程名
- version標簽:當前工程的版本號
- dependencies標簽:用於管理這個工程的依賴
- dependency標簽:指定某個依賴的信息
- groupId:標識依賴包的所屬組織,寫法類似包名。
- artifactId:依賴包的包名。
- version:依賴包的版本。
- scope標簽:依賴包的依賴范圍。
- dependency標簽:指定某個依賴的信息
依賴級別\依賴范圍
依賴信息中的scope標簽是用來定義依賴范圍的。依賴范圍影響依賴的生存周期(就好比游戲中的特殊狀態,可能一些狀態可用於pk,一些狀態可用於打副本,一些狀態可用於任務,不同的地方影響效果是否生效。),依賴范圍的值有以下幾個:
- compile:編譯級別的依賴會用在編譯、測試、運行的過程中。默認依賴范圍:compile。
- test:test僅僅針對test目錄下的源文件,由於test目錄下存放的是test文件,測試文件一般都不會編譯到主程序中,所以test級別的依賴是不會在編譯和運行中生效的。只在測試編譯和測試運行階段可用。這個級別的依賴包例如有junit包,junit僅僅用來測試,在主程序編譯和運行中是不需要它的。
- provided:provided代表已提供的意思,provided范圍會用來編譯和測試,不會出現在運行中,provided主要用來處理容器也提供了我們所需要的包的情況。例如servlet-api這種依賴包tomcat容器也會提供給部署的程序,如果提供多個同名的依賴包可能會導致主程序運行出錯。
- runtime:在編譯的時候不需要(沒有用到具體類),但是在運行和測試的時候需要用到,就可以使用這個。例如數據庫驅動包,它僅僅在運行和測試的時候會使用到這個依賴包。
- system:類似provided,對於編譯和測試有效,運行時不需要,不建議使用,所以不講。
依賴傳遞的導入
要注意,在一個工程中,如果導入的依賴需要一系列依賴(A包需要B包才能正常,那么也會導入B包),那么也會導入這一些依賴,例如struts2-core依賴一系列的包。
演示:基於eclipse
僅僅導入struts2-core的時候,maven會自動導入struts2-core所依賴的包:
發現maven自動導入了struts2-core依賴的包(這些依賴包是由struts2-core項目中的pom.xml指定的)
依賴傳遞問題
- 依賴傳遞的過程中:
- 路徑最短者優先
- A依賴B,B依賴C,C依賴D(版本1.1)
- A依賴E,E依賴D(版本1.2)
- 導入時選擇版本D(版本1.2)
- 路徑相同,先聲明者優先【意思是如果A同時依賴於B和C,而B和C都含有同一個依賴包P,如果在A的繼承聲明中先聲明B,那么A會繼承B的依賴包P,所以P版本取決於B】
- 路徑最短者優先
依賴排除
可能會遇到一種情況,在同一個工程中,A包依賴B包的1.0版本,C包依賴B包的1.5版本。那么B的1.0和1.5都被引入了。這可能會導致紊亂,因為構建的時候會不清楚使用哪個版本的B依賴包。這時候我們需要使用依賴排除來解決這個問題。【一般都是排除低版本】
例如struts2-core依賴javassist包,hibernate-core也依賴javassist包,根據依賴的依賴的導入規則,這時候會有兩個javassist
為了避免紊亂,我們要使用exclusions排除。在eclipse中,我們可以在Dependency Hierarchy中右鍵選中包進行排除,也可以使用以下xml式排除:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.34</version>
<exclusions>
<!-- 排除struts2-core的依賴中的javassist依賴 -->
<exclusion>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>
依賴的繼承
在建立多個有繼承關系的工程時,父工程的依賴信息會傳遞給子工程。
在父工程中聲明了依賴后,就算子工程沒有聲明,也會傳遞到子工程中
版本鎖定
在分模塊開發時,多個子模塊可能會使用上同一個依賴包,那么如何限定多個子模塊都使用同一版本的依賴包呢?可以使用版本鎖定。
- 在父工程使用dependencyManagement來管理依賴(dependencyManagement不會導入依賴),那么依賴的版本會被父工程鎖定。
- 通常情況下,父工程的依賴會傳遞給子工程(如果你另外也使用了dependencies標簽來聲明依賴),那么子工程不聲明的時候是沒問題的;如果子工程顯式導入被鎖定版本的依賴時,會報錯,會提示版本被父工程鎖定。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
統一管理依賴版本:
你應該經常見到某個框架的依賴包都是同一版本的,如果我們將這些依賴信息都添加到pom.xml中,可能會出現多個重復的version標簽,如果你要修改的話是很麻煩的,要逐個逐個去修改版本。
事實上,是可以統一管理依賴版本的,同一管理依賴版本之后,如果我們要修改這個框架下的包的版本,那么只需要修改一處就行了。
- 使用properties內使用自定義標簽統一版本號,自定義標簽相當於一個變量,后面的version那里可以引用這個變量。
<properties>
<!-- 使用自定義標簽統一版本號,標簽名是自定義的 -->
<struts2-version>2.3.34</struts2-version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<!--在version標簽中引用 -->
<version>${struts2-version}</version>
</dependency>
</dependencies>
注意:properties標簽並不是只能用於統一聲明依賴版本,但凡是需要統一聲明的地方都可以考慮使用properties標簽。
Maven命令
全局命令
- maven -v :查看版本
工程級命令
以下命令針對於maven工程,必須到pom.xml目錄才能執行命令
- mvn clean:清理之前編譯出的class文件,相當於清理target目錄及其目錄下的所有文件。
- mvn compile:編譯主程序,效果是把src/main/java下的java源文件編譯為class文件並輸出到target下的classes目錄下。
- mvn test-compile:編譯測試程序
- mvn test:執行src/test/java下的單元測試類,會打印出測試結果(如果被junit標識成測試類的話),並把src/main/java下的java源文件編譯為class文件並輸出到target下的test-classes目錄下。
- mvn package:打包,java項目打包成jar包,web項目打包成war包。打包的文件存儲到target目錄下。
- mvn install:安裝,把maven工程打包成jar包或war包並保存到本地倉庫中。【在本地倉庫目錄下根據坐標來生成包路徑來保存】。對於我們自己的maven工程,可以使用mvn install把它安裝到倉庫中。
命令生命周期
- 屬於同一個生命周期的指令,當后面的命令執行時,前面的命令也會自動執行。
- 常見命令周期:
- clean :在進行真正構建之前的一些清理工作。
- 包含命令:pre-clean,clean,post-clean
- default:構建的核心部分:編譯、測試、打包、部署等等。【要注意,大部分命令都處於default生命周期,所以執行某個命令時,生命周期前面的命令也會自動執行。】
- 包含命令:validate,compile,test,package,verify,install,deploy....
- site:生成項目報告、站點、發布站點。。
- 包含命令:pre-site,site,post-site,site-deploy
- clean :在進行真正構建之前的一些清理工作。
每一個階段都有一個對應的命令,且有相應的插件來支持命令的運行。
setting.xml配置文件
倉庫配置
本地倉庫配置
maven安裝路徑下\conf\settings.xml文件,在settings.xml中配置localResposity標簽。,它是被注釋了的,有配置方法的提示。
默認目錄:用戶目錄下.m2/repository
添加遠程倉庫
<mirrors>
<!-- 中央倉庫1 -->
<mirror>
<id>repo1</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://repo1.maven.org/maven2/</url>
</mirror>
<!-- 中央倉庫2 -->
<mirror>
<id>repo2</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://repo2.maven.org/maven2/</url>
</mirror>
</mirrors>
Eclipse中使用maven
配置maven
eclipse有自帶的maven插件,但不建議使用。
把獨立的maven添加成一個新的maven:
配置user settings:
創建maven工程:
【maven model用於分模塊開發時創建子工程,多個子工程與核心工程組成一個完整的項目。】
新建工程->選擇maven project
下面給的是打包方式為war的時候的目錄結構:
修改JRE版本:
默認情況下,maven工程引用的jre庫是1.5的,這可能會導致一些語法問題(例如泛型的語法問題),所以通常需要更改這個引用的jre庫版本。
- 修改方法:在setting.xml中修改profiles標簽
<profile>
<id>jdk18</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
<maven.compiler.encoding>utf-8</maven.compiler.encoding>
</properties>
</profile>
導入依賴
-
方式一:手動添加,通過手動拷貝等方式統一增加。可以百度
包名+maven
來查找依賴信息的寫法,拷貝下來粘貼到pom.xml中即可。-
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
-
-
方式二:在eclipse,雙擊打開pom.xml,默認情況下不是xml界面,點擊下面的dependencies選項,再點擊add,在中間的搜索框輸入信息搜索依賴,選擇依賴包,最后點擊確認。這要求你比較熟悉需要哪些包。
添加插件
有時候我們希望給maven工程添加額外的插件,例如tomcat7:run插件,這個插件能使得我們的工程虛擬地部署到tomcat中。
-
mvn tomcat:run 命令是一個插件,需要添加才能執行這條命令,添加方式:項目右鍵選擇maven,再add plugin,然后搜索tomcat
-
<!--build與dependencies是同一級的 --> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin> <configuration> <!-- 端口 --> <port>8080</port> <!-- 訪問路徑 --> <path>/helloworld</path> <!-- 編碼 --> <uriEncoding>utf-8</uriEncoding> </configuration> </plugins> </build>
-
這里僅僅給一個添加插件的示例,其他的插件有興趣可以自查。
Eclipse中執行maven命令
工程右鍵->run as ->第一個maven build可以讓你選擇之前執行過的命令來執行,第二個maven build可以讓你輸入指定命令來執行(在goals中輸入命令,mvn test只需要輸入test即可);至於后面的clean,install和test的意思已經顯而易見了。
創建web工程
如果想創建一個web工程,需要在創建工程的時候打包方式改成war。但默認情況下src/main下是沒有webapp目錄(存放WEB-INF目錄和web.xml的目錄)的。
- 生成webapp目錄:
- 方式一: WEB-INF目錄和web.xml,javaEE tools->Generate Deploy...
- 方式二:手動創建目錄和文件
依賴范圍沖突問題:
什么是依賴范圍沖突呢?這涉及到依賴范圍問題,主要是provided問題。以servlet-api依賴為例,這個依賴tomcat會提供給我們部署的項目,但如果我們添加這個依賴的時候選擇了compile,那么這個依賴也會帶到部署的項目中,使得存在了兩個servlet-api依賴。
解決方法:這時候要修改servlet-api依賴的范圍,改成provided。
依賴排除問題:
這個在pom配置的依賴排除中講過了。這里只提一下,不再演示。
如何運行項目
java項目:
- 運行方式一:項目右鍵->run as->java application
- 由於方式二跟直接到目標目錄執行java沒什么區別,所以這里不講,有興趣可以自查
mvn exec
。
web項目:
- 部署方式一:在添加了插件之后,使用tomcat插件部署:mvn tomcat7:run
- 選擇5 Maven build之后,輸入命令
tomcat7:run
- 區別:插件的是虛擬環境,會比較快。
- 選擇5 Maven build之后,輸入命令
- 部署方式二:打成war包之后,把war包拷貝到tomcat目錄中。
- 部署方式三:建立服務器之后,把項目添加到tomcat中;或者在pom.xml文件點擊右鍵,直接把項目添加到tomcat中。
工程拆分和聚合
- 在一個比較大的項目開發協作中,如果按照以前的開發的話,是一個工程。這樣會有一些問題。拆分、分模塊便於測試和開發。不同開發者僅僅面向自己的工程。
- 然后在整合的時候,把工程聚合起來,就能聚合成一個完整的項目了。
工程的拆分
工程的拆分是創建一個核心父工程,然后創建多個子模塊的情況。核心父工程一般不會編寫什么內容,一般只作為依賴的匯總(讓父工程引入共有依賴,子工程單獨依賴的單獨引入)。
創建父工程:
創建子工程
為了讓父工程能管理到子工程,所以在父工程下右鍵"new-->maven module"
創建完父工程和子模塊后,可以在父工程的pom.xml中看到父工程管理到了子模塊:
而子模塊也指向了父工程:
然后子模塊怎么開發呢?它相當於與一個獨立的模塊,所以你可以像往常一樣開發。不過提一下的是,可能會發生service層調用dao層,那么這怎么實現呢?這就需要我們在service層中添加dao層的依賴了,這樣service層就可以調用dao層的方法了。
這里提一下工程拆分與框架整合的問題,在以前一個工程中,dao和service都是交給spring去管理的,那么現在
該怎么處理呢?首先,要注意的是,只要我們配置了spring(這里注意,依賴已經導入了),無論是xml還是注解
式,那么spring就能夠管理好我們的bean。所以,我們現在其實只需要關心我們的bean是否交給了spring來管理
即可。而這個單個模塊的測試可以在test目錄下再編寫代碼來測試。
工程的聚合
拆分工程之后,開發完成了,怎么聚合使用呢?
首先,要注意父工程管理着子模塊,
如果打包父工程,那么子工程也會進行打包。
而通常我們在進行web開發的時候,由於子模塊web是核心項目,而子模塊web又依賴着子模塊service,而在打包的時候依賴的包也會打成jar包,所以打包子模塊web的時候,web工程的lib里面是有依賴的兄弟工程的,所以我們可以直接運行web工程即可。【這是運行war包的情況】
我們也可以選擇在IDE中直接運行子模塊web(在eclipse直接run as),也是能夠調用到其他兄弟模塊的功能的。
寫在最后
這篇關於maven的博文看完了,你應該能對maven的使用有一個基本的了解。
這里給一個常用的查maven的依賴信息的網站:mvnrepository.com