面试必会系列 - 11.1 一文读懂Maven:Maven工程类型、项目结构、工程关系、常见命令等
本文已收錄至 Github(MD-Notes),若博客中圖片模糊或打不開,可以來我的 Github 倉庫,包含了完整圖文:https://github.com/HanquanHq/MD-Notes,涵蓋了互聯網大廠面試必問的知識點,講解透徹,長期更新中,歡迎一起學習探討 ~
更多內容,可以訪問:
面試必會系列專欄:https://blog.csdn.net/sinat_42483341/category_10300357.html
操作系統系列專欄:https://blog.csdn.net/sinat_42483341/category_10519484.html
目錄
- Maven詳解
- 什么是Maven
- Maven的下載目錄結構、IDEA整合Maven
- 【1】IDEA默認整合了Maven:
- 【2】下載地址:
- 【3】目錄結構:
- 【4】如果沒有.m2目錄 ,自己手動執行mvn命令:
- Maven倉庫
- 遠程倉庫
- 本地倉庫
- 倉庫配置
- 在settings.xml文件中配置本地倉庫
- 在settings.xml文件中配置鏡像倉庫
- 倉庫優先級問題
- JDK的配置
- 總結:
- Maven工程類型
- 【1】POM工程
- 【2】JAR工程
- 【3】WAR工程
- 在IDEA中創建Maven工程
- 【1】過程:
- Maven項目結構
- ?src/main/java
- ?src/main/resources
- ?src/test/java
- ?src/test/resources
- ?src
- ?target
- ?pom.xml
- 目錄結構圖:
- 注意:
- POM模式-Maven工程關系
- 依賴關系
- 【1】依賴關系:
- 【2】如何注入依賴呢?
- 【3】依賴的好處:
- 特性_依賴的傳遞性
- 案例:
- 原則:兩個原則
- 【1】第一原則:最短路徑優先原則
- 【2】第二原則:最先聲明原則
- 排除依賴
- 依賴范圍(重要!)
- ?compile
- ?provided(重要)
- ?runtime
- ?system
- ?test
- ?Import
- 補充:dependencyManagement的使用
- 繼承關系
- 聚合關系
- Maven常見插件
- 編譯器插件
- 【1】 settings.xml文件中配置全局編譯器插件:
- 【2】配置編譯器插件:pom.xml配置片段
- 資源拷貝插件
- tomcat 插件
- Maven常見命令介紹
- ? install
- ? clean
- ? compile
- ? package
- 注:install和package的區別
Maven詳解
什么是Maven
目前無論使用IDEA還是Eclipse等其他IDE,使用里面ANT工具。ANT工具幫助我們進行編譯,打包運行等工作。Apache基于ANT進行了升級,研發出了全新的自動化構建工具Maven。Maven是Apache的一款開源的項目管理工具。以后無論是普通javase項目還是javaee項目,我們都創建的是Maven項目。
Maven使用項目對象模型(POM-Project Object Model,項目對象模型)的概念,可以通過一小段描述信息來管理項目的構建,報告和文檔的軟件項目管理工具。在Maven中每個項目都相當于是一個對象,對象(項目)和對象(項目)之間是有關系的。關系包含了:依賴、繼承、聚合,實現Maven項目可以更加方便的實現導jar包、拆分項目等效果。
Maven的下載目錄結構、IDEA整合Maven
【1】IDEA默認整合了Maven:
【2】下載地址:
http://maven.apache.org/
【3】目錄結構:
bin:存放的是執行文件,命令
在IDEA中可以直接集成Maven:
conf目錄:下面有一個非常重要的配置文件–> settings.xml —> maven的核心配置文件/全局配置文件。
【4】如果沒有.m2目錄 ,自己手動執行mvn命令:
mvn help:system
Maven倉庫
Maven倉庫是基于簡單文件系統存儲的,集中化管理Java API資源(構件)的一個服務。
倉庫中的任何一個構件都有其唯一的坐標,根據這個坐標可以定義其在倉庫中的唯一存儲路徑。得益于 Maven 的坐標機制,任何 Maven項目使用任何一個構件的方式都是完全相同的。
Maven 可以在某個位置統一存儲所有的 Maven 項目共享的構件,這個統一的位置就是倉庫,項目構建完畢后生成的構件也可以安裝或者部署到倉庫中,供其它項目使用。
對于Maven來說,倉庫分為兩類:本地倉庫、遠程倉庫。
遠程倉庫
不在本機中的一切倉庫,都是遠程倉庫:分為 中央倉庫 和 本地私服倉庫
遠程倉庫指通過各種協議如file://和http://訪問的其它類型的倉庫。這些倉庫可能是第三方搭建的真實的遠程倉庫,用來提供他們的構件下載(例如repo.maven.apache.org和uk.maven.org是Maven的中央倉庫)。其它“遠程”倉庫可能是你的公司擁有的建立在文件或HTTP服務器上的內部倉庫(不是Apache的那個中央倉庫,而是你們公司的私服,你們自己在局域網搭建的maven倉庫),用來在開發團隊間共享私有構件和管理發布的。
默認的遠程倉庫使用的Apache提供的中央倉庫:
https://mvnrepository.com/
本地倉庫
本地倉庫指本機的一份拷貝,用來緩存遠程下載,包含你尚未發布的臨時構件。
倉庫配置
在settings.xml文件中配置本地倉庫
本地倉庫是開發者本地電腦中的一個目錄,用于緩存從遠程倉庫下載的構件。默認的本地倉庫是${user.home}/.m2/repository。用戶可使用settings.xml文件修改本地倉庫。具體內容如下:
<?xml version="1.0" encoding="UTF-8"?> <settingsxmlns="http://maven.apache.org/SETTINGS/1.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"><!-- 本地倉庫配置 --><localRepository>具體本地倉庫位置</localRepository><!-- 省略,具體信息參考后續內容。 --> </settings>在settings.xml文件中配置鏡像倉庫
如果倉庫A可以提供倉庫B存儲的所有內容,那么就可以認為A是B的一個鏡像。例如:在國內直接連接中央倉庫下載依賴,由于一些特殊原因下載速度非常慢。這時,我們可以使用阿里云提供的鏡像http://maven.aliyun.com/nexus/content/groups/public/來替換中央倉庫http://repol.maven.org/maven2/。修改maven的setting.xml文件,具體內容如下:
<mirror><!-- 指定鏡像ID(可自己改名) --><id>nexus-aliyun</id><!-- 匹配中央倉庫(阿里云的倉庫名稱,不可以自己起名,必須這么寫)--><mirrorOf>central</mirrorOf><!-- 指定鏡像名稱(可自己改名) --><name>Nexus aliyun</name><!-- 指定鏡像路徑(鏡像地址) --><url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror>倉庫優先級問題
優先級別:
JDK的配置
當你的idea中有多個jdk的時候,就需要指定你編譯和運行的jdk。在settings.xml中配置:
<profile><!-- settings.xml中的id不能隨便起的 --><!-- 告訴maven我們用jdk1.8 --><id>jdk-1.8</id><!-- 開啟JDK的使用 --><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></properties> </profile>配置的前提是,你的idea中要有1.8的jdk
總結:
在settings.xml中:配置了三個信息:
【1】本地倉庫
【2】鏡像倉庫
【3】JDK
Maven工程類型
【1】POM工程
POM工程是邏輯工程。用在父級工程或聚合工程中。用來做jar包的版本控制。
【2】JAR工程
將會打包成jar,用作jar包使用。即常見的本地工程 —> Java Project。
【3】WAR工程
將會打包成war,發布在服務器上的工程。
在IDEA中創建Maven工程
【1】過程:
標準目錄結構:
Maven項目結構
標準目錄結構:
?src/main/java
這個目錄下儲存java源代碼
?src/main/resources
儲存主要的資源文件。比如xml配置文件和properties文件
?src/test/java
儲存測試用的類,比如JUNIT的測試一般就放在這個目錄下面
因為測試類本身實際是不屬于項目的,所以放在任何一個包下都顯得很尷尬,所以maven專門創建了一個測試包
用于存放測試的類
?src/test/resources
可以自己創建你,儲存測試環境用的資源文件
?src
包含了項目所有的源代碼和資源文件,以及其他項目相關的文件。
?target
編譯后內容放置的文件夾
?pom.xml
是Maven的基礎配置文件。配置項目和項目之間關系,包括配置依賴關系等等
目錄結構圖:
–MavenDemo 項目名
–.idea 項目的配置,自動生成的,無需關注。
–src
–main 實際開發內容
–java 寫包和java代碼,此文件默認只編譯.java文件
–resource 所有配置文件。最終編譯把配置文件放入到classpath中。
– test 測試時使用,自己寫測試類或junit工具等
–java 儲存測試用的類
pom.xml 整個maven項目所有配置內容。
注意:
目錄名字不可以隨便改,因為maven進行編譯或者jar包生成操作的時候,是根據這個目錄結構來找的,你若輕易動,那么就找不到了。
POM模式-Maven工程關系
Maven工具基于POM(Project Object Model,項目對象模型)模式實現的。在Maven中每個項目都相當于是一個對象,對象(項目)和對象(項目)之間是有關系的。關系包含了:依賴、繼承、聚合,實現Maven項目可以更加方便的實現導jar包、拆分項目等效果。
依賴關系
【1】依賴關系:
即A工程開發或運行過程中需要B工程提供支持,則代表A工程依賴B工程。
在這種情況下,需要在A項目的pom.xml文件中增加下屬配置定義依賴關系。
通俗理解:就是導jar包。
B工程可以是自己的項目打包后的jar包,也可以是中央倉庫的jar包。
【2】如何注入依賴呢?
在pom.xml文件 根元素project下的 dependencies標簽中,配置依賴信息,內可以包含多個 dependence元素,以聲明多個依賴。每個依賴dependence標簽都應該包含以下元素:groupId, artifactId, version : 依賴的基本坐標, 對于任何一個依賴來說,基本坐標是最重要的, Maven根據坐標才能找到需要的依賴。
【3】依賴的好處:
省去了程序員手動添加jar包的操作,省事!!
可以幫我們解決jar包沖突問題:
特性_依賴的傳遞性
傳遞性依賴是Maven2.0的新特性。假設你的項目依賴于一個庫,而這個庫又依賴于其他庫。你不必自己去找出所有這些依賴,你只需要加上你直接依賴的庫,Maven會隱式的把這些庫間接依賴的庫也加入到你的項目中。這個特性是靠解析從遠程倉庫中獲取的依賴庫的項目文件實現的。一般的,這些項目的所有依賴都會加入到項目中,或者從父項目繼承,或者通過傳遞性依賴。
如果A依賴了B,那么C依賴A時會自動把A和B都導入進來。
創建A項目后,選擇IDEA最右側Maven面板lifecycle,雙擊install后就會把項目安裝到本地倉庫中,其他項目就可以通過坐標引用此項目。
案例:
項目1:MavenDemo項目依賴了Mybatis的內容:
注意:請將項目1打包為jar包—》重新打包
再創建項目2:讓項目2依賴項目1:
從上面可以證明:項目2依賴項目1,項目1依賴Mybatis工程,–》傳遞性—》項目2可以直接使用Mybatis工程
原則:兩個原則
【1】第一原則:最短路徑優先原則
“最短路徑優先”意味著項目依賴關系樹中路徑最短的版本會被使用。
例如,假設A、B、C之間的依賴關系是A->B->C->D(2.0) 和A->E->(D1.0),那么D(1.0)會被使用,因為A通過E到D的路徑更短。
【2】第二原則:最先聲明原則
依賴路徑長度是一樣的的時候,第一原則不能解決所有問題,比如這樣的依賴關系:A–>B–>Y(1.0),A–>C–>Y(2.0),Y(1.0)和Y(2.0)的依賴路徑長度是一樣的,都為2。那么到底誰會被解析使用呢?在maven2.0.8及之前的版本中,這是不確定的,但是maven2.0.9開始,為了盡可能避免構建的不確定性,maven定義了依賴調解的第二原則:第一聲明者優先。在依賴路徑長度相等的前提下,在POM中依賴聲明的順序決定了誰會被解析使用。順序最靠前的那個依賴優勝。
排除依賴
exclusions: 用來排除傳遞性依賴 其中可配置多個exclusion標簽,每個exclusion標簽里面對應的有groupId, artifactId, version三項基本元素。注意:不用寫版本號。
比如:A—>B—>C (Mybatis.jar) 排除C中的Mybatis.jar
依賴范圍(重要!)
依賴范圍就決定了你依賴的坐標 在什么情況下有效,什么情況下無效:
?compile
這是默認范圍。如果沒有指定,就會使用該依賴范圍。表示該依賴在編譯和運行時都生效。
?provided(重要)
已提供依賴范圍。使用此依賴范圍的Maven依賴。典型的例子是servlet-api,編譯和測試項目的時候需要該依賴,但在運行項目的時候,由于容器已經提供,就不需要Maven重復地引入一遍(如:servlet-api,例如tomcat)
?runtime
runtime范圍表明編譯時不需要生效,而只在運行時生效。典型的例子是JDBC驅動實現,項目主代碼的編譯只需要JDK提供的JDBC接口,只有在執行測試或者運行項目的時候才需要實現上述接口的具體JDBC驅動。
?system
系統范圍與provided類似,不過你必須顯式指定一個本地系統路徑的JAR,此類依賴應該一直有效,Maven也不會去倉庫中尋找它。但是,使用system范圍依賴時必須通過systemPath元素顯式地指定依賴文件的路徑。
?test
test范圍表明使用此依賴范圍的依賴,只在編譯測試代碼和運行測試的時候需要,應用的正常運行不需要此類依賴。典型的例子就是JUnit,它只有在編譯測試代碼及運行測試的時候才需要。Junit的jar包就在測試階段用就行了,你導出項目的時候沒有必要把junit的東西到處去了就,所在在junit坐標下加入scope-test
?Import
補充:dependencyManagement的使用
作用:Maven中的dependencyManagement元素提供了一種管理依賴版本號的方式。在dependencyManagement元素中聲明所依賴的jar包的版本號等信息,那么所有子項目再次引入此依賴jar包時則無需顯式的列出版本號。Maven會沿著父子層級向上尋找擁有dependencyManagement 元素的項目,然后使用它指定的版本號。
如果有多個子項目都引用同一樣依賴,則可以避免在每個使用的子項目里都聲明一個版本號。當想升級或切換到另一個版本時,只需要在頂層父容器里更新,而不需要逐個修改子項目;另外如果某個子項目需要另外的一個版本,只需要聲明version即可。
注意:dependencyManagement中定義的只是依賴的聲明,并不實現引入,因此子項目需要顯式的聲明需要用的依賴。
import范圍只適用于pom文件中的部分。表明指定的POM必須使用部分的依賴。
注意:import只能用在dependencyManagement的scope里。
定義一個父工程 -->POM工程:
注意:工程1要 mvn install 打成自己的jar包,提供給子工程用
定義一個子工程:(里面寫上父工程的坐標)
如果父工程中加入score-import,相當于強制的指定了版本號,子工程在引入父工程的時候,強制使用父工程的版本號,即子工程無法指定自己的版本號。
繼承關系
如果A工程繼承B工程,則代表A工程默認依賴B工程依賴的所有資源,且可以應用B工程中定義的所有資源信息。被繼承的工程(B工程)只能是POM工程。
注意:在父項目中放在<dependencyManagement>中的內容時不被子項目繼承,不可以直接使用
放在<dependencyManagement>中的內容主要目的是進行版本管理。里面的內容在子項目中依賴時坐標只需要填寫<group id>和<artifact id>即可。(注意:如果子項目不希望使用父項目的版本,可以明確配置version)。
父工程是一個POM工程:
創建子工程:
繼承關系在本質上,是POM文件的繼承
聚合關系
當我們開發的工程擁有2個以上模塊的時候,每個模塊都是一個獨立的功能集合。比如某大學系統中擁有搜索平臺,學習平臺,考試平臺等。開發的時候每個平臺都可以獨立編譯,測試,運行。這個時候我們就需要一個聚合工程。
在創建聚合工程的過程中,總的工程必須是一個POM工程(Maven Project)(聚合項目必須是一個pom類型的項目,jar項目war項目是沒有辦法做聚合工程的),各子模塊可以是任意類型模塊(Maven Module)。
前提:繼承。
聚合包含了繼承的特性。
聚合時多個項目的本質還是一個項目。這些項目被一個大的父項目包含。且這時父項目類型為pom類型。同時在父項目的pom.xml中出現表示包含的所有子模塊。
總項目:一般總項目:POM項目
具體模塊:
Maven常見插件
編譯器插件
通過編譯器插件,我們可以配置使用的JDK或者說編譯器的版本:
【1】 settings.xml文件中配置全局編譯器插件:
找到profiles節點,在里面加入profile節點:
<profile><!-- 定義的編譯器插件ID,全局唯一,名字隨便起 --><id>jdk-1.7</id><!-- 插件標記,activeByDefault :true默認編譯器,jdk提供編譯器版本 --><activation><activeByDefault>true</activeByDefault><jdk>1.7</jdk></activation><!-- 配置信息source-源信息,target-字節碼信息,compilerVersion-編譯過程版本 --><properties><maven.compiler.source>1.7</maven.compiler.source><maven.compiler.target>1.7</maven.compiler.target><maven.compiler.compilerVersion>1.7</maven.compiler.compilerVersion></properties> </profile>【2】配置編譯器插件:pom.xml配置片段
<!-- 配置maven的編譯插件 --> <build><plugins><!--JDK編譯插件 --><plugin><!--插件坐標 --><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.2</version><!-- --><configuration><!-- 源代碼使用JDK版本--><source>1.7</source><!-- 源代碼編譯為class文件的版本,要保持跟上面版本一致--><target>1.7</target><encoding>UTF-8</encoding></configuration></plugin></plugins> </build>資源拷貝插件
Maven在打包時默認只將src/main/resources里的配置文件拷貝到項目中并做打包處理,而非resource目錄下的配置文件在打包時不會添加到項目中。
我們的配置文件,一般都放在:src/main/resources,然后打包后配置文件就會在target的classes下面放著:
測試:
我現在想把非resources下面的文件也打包到classes下面,需要配置:
pom.xml配置片段:
配置好以后,那么你設置的位置下的配置文件都會被打包了:
tomcat 插件
我們如果創建war項目,必然要部署在服務器上,方式:
(1)部署在遠程服務器上
(2)將IDEA和外部tomcat產生關聯,然后將項目部署在外部tomcat上
現在學習一個新的方式,不再依賴外部的tomcat,maven提供了tomcat插件,我們可以配置來使用。
創建web項目(war項目):
使用Tomcat插件發布部署并執行war工程的時候,需要使用啟動命令,啟動命令為: tomcat7:run。命令中的tomcat7是插件命名,由插件提供商決定。run為插件中的具體功能。
(注意:之前用的編譯器插件,資源拷貝插件,不是可運行的插件,maven直接幫我們運行了,但是tomcat屬于可運行插件,它什么時候工作需要程序員來控制,怎么控制呢?我們必須通過命令來運行控制)
具體pom.xml文件的配置如下:
右側maven執行命令tomcat7:run:
看到運行結果,顯示tomcat啟動成功。在瀏覽器中訪問index.jsp頁面。
Maven常見命令介紹
Maven的命令非常多,我們只是講解常用的幾個:(所有命令都可以在控制臺運行的)
? install
本地安裝, 包含編譯,打包,安裝到本地倉庫
編譯 - javac
打包 - jar, 將java代碼打包為jar文件
安裝到本地倉庫 - 將打包的jar文件,保存到本地倉庫目錄中。
? clean
清除已編譯信息。
刪除工程中的target目錄。
? compile
只編譯。 javac命令
? package
打包。 包含編譯,打包兩個功能。
注:install和package的區別
-
package 命令完成了項目編譯、單元測試、打包功能,但沒有把打好的可執行jar包(war包或其它形式的包)布署到本地maven倉庫和遠程maven私服倉庫
-
install 命令完成了項目編譯、單元測試、打包功能,同時把打好的可執行jar包(war包或其它形式的包)布署到本地maven倉庫,但沒有布署到遠程maven私服倉庫
總結
以上是生活随笔為你收集整理的面试必会系列 - 11.1 一文读懂Maven:Maven工程类型、项目结构、工程关系、常见命令等的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面试必会系列 - 5.2 详解OSI模型
- 下一篇: 面试必会系列 - 5.3 LVS负载均衡