1. 程式人生 > 程式設計 >一篇文章帶你搞定JAVA Maven

一篇文章帶你搞定JAVA Maven

目錄
  • 1、maven是什麼,為什麼存在?專案結構是什麼樣子,怎麼定位jar
  • 2、Idea 的操作
    • 1.新建maven專案
    • 2.配置倉庫
    • 3.新增依賴,新增faston的依賴
    • 4.打包專案
  • 3、Maven座標主要組成
    • 4、maven生命週期
      • 4.1 名詞解釋
      • 4.2 生命週期
      • 4.3 goal 的概念
      • 4.4 生命週期和phase的關係
    • 5、idea maven的配置
      • 6、POM有2個很重要的關係:聚合、繼承
        • 一、聚合
        • 二、繼承
      • 7、Maven 中的 profile
        • 8、maven 外掛
          • 9、環境變數
            • 10、Maven 依賴衝突的2個方法
              • 1.統一版本
              • 2.排除依賴
            • 11、scope
              • 總結:

                1、maven是什麼,為什麼存在?專案結構是什麼樣子,怎麼定位jar

                官方說了好多,整的多複雜一樣,簡單說:maven是一個管理包的工具。

                MavsxKmFen 存在的必要性是什麼吶?想想開源的jar包如此之多,版本又如此之多,在沒有Maven之前,我們管理jar包全部都是下載之後建立一個lib的資料夾,然後專案進行引用,在其他的專案成員需要修改一個jar的時候需要到處拷貝,在部署的時候也很麻煩,問題存在就要解決,因此出現了Maven,統一管理,統一的倉庫,只需要配置是要哪個版本的包,直接下載就夠了,不用拷貝,是不是很方便。

                現在大的問題解決了,怎麼定位一個jar包吶?

                圖片

                2、Idea 的操作

                1.新建maven專案

                File ->新建->project

                圖片

                勾選從原型(模板)建立,選擇maven-archetype-qiuckstart

                圖片

                填入專案的名字,和groupId (公司域名反過來,如com.alibaba)

                圖片

                選擇本地倉庫的位置,和自定義的setting配置

                圖片

                一路finish,然後等待idea 建立模板專案就好了。

                2.配置倉庫

                Maven 倉庫有三種類型:

                • 本地(local)
                • 中央(central)
                • 遠端(remote)

                當我們執行 Maven 構建命令時,Maven 開始按照以下順序查詢依賴的庫

                步驟 1 - 在本地倉庫中搜索,如果找不到,執行步驟 2,如果找到了則執行其他操作。

                步驟 2 - 在中央倉庫中搜索,如果找不到,並且有一個或多個遠端倉庫已經設定,則執行步驟 4,如果找到了則下載到本地倉庫中以備將來引用。

                步驟 3 - 如果遠端倉庫沒有被設定,Maven 將簡單的停滯處理並丟擲錯誤(無法找到依賴的檔案)。

                步驟 4 - 在一個或多個遠端倉庫中搜索依賴的檔案,如果找到則下載到本地倉庫以備將來引用,否則 Maven 將停止處理並丟擲錯誤(無法找到依賴的檔案)。

                阿里雲倉庫配置:

                 <repositories>
                       <repository>
                           <id>central</id>
                           <name>aliyun maven</name>
                           <url>https://maven.aliyun.com/repository/public/</url>
                           <layout>default</layout>
                           <!-- 是否開啟發布版構件下載 -->
                           <releases>
                               <enabled>true</enabled>
                           </releases>
                           <!-- 是否開啟快照版構件下載 -->
                           <snapshots>
                               <enabled>false</enabled>
                           </snapshots>
                       </repository>
                   </repositories>

                3.新增依賴,新增fastjson的依賴

                舉個例子:

                  <dependency>
                           <groupId>com.alibaba</groupId>
                           <artifactId>fastjson</artifactId>
                       </dependency>

                4.打包專案

                圖片

                3、Maven座標主要組成

                • groupId:組織標識(包名),一般常用公司域名的反序,比如com.alibaba
                • artifactId:專案名稱,專案的具體名稱
                • version:專案的當前版本 ,一般版本號為 大版本.小版本.小版本序號
                • packaging:專案的打包方式,最為常見的jar和war兩種

                4、maven生命週期

                4.1 名詞解釋

                lifecycle:生命週期,這是maven最高級別的的控制單元,它是一系列的phase組成,也就是說,一個生命週期,就是一個大任務的總稱,不管它裡面分成多少個子任務,反正就是執行一個lifecycle,就是交待了一個任務,執行完後,就得到了一個結果,中間的過程,是phase完成的,自己可以定義自己的lifecycle,包含自己想要的phase

                phase:可以理解為任務單元,lifecycle是總任務,phase就是總任務分出來的一個個子任務,但是這些子任務是被規格化的,它可以同時被多個lifecycle所包含,一個lifecycle可以包含任意個phase,phase的執行是按順序的,一個phase可以繫結很多個goal,至少為一個,沒有goal的phase是沒有意義的

                goal: 這是執行任務的最小單元,它可以繫結到任意個phase中,一個phase有一個或多個goal,goal也是按順序執行的,一個phase被執行時,繫結到phase裡的goal會按繫結的時間被順序執行,不管phase己經綁定了多少個goal,你自己定義的goal都可以繼續綁到phase中

                mojo: lifecycle與phase與goal都是概念上的東西,mojo才是做具體事情的,可以簡單理解mojo為goal的實現類,它繼承於AbstractMojo,有一個execute方法,goal等的定義都是通過在mojo裡定義一些註釋的anotation來實現的,maven會在打包時,自動根據這些anotation生成一些xml檔案,放在plugin的jar包裡

                可以通俗理解為lifecyle 是一個公司,phrase 是具體的部門,goal 是一個專案,Mojo 是專案內部的人,其他的都是管理層級,具體的執行還是人。

                4.2 生命週期

                圖片

                4.3 goal 的概念

                一個goal是獨立的,它可以被繫結到多個phase中去,也可以一個phase都沒有。如果一個goal沒有被繫結到任何一個lifecycle,它仍然可以直接被呼叫,而不是被lifecycle呼叫。

                因此可以這樣理解phase與goal的關係:

                1.phase其實就是goal的容器。實際被執行的都是goal。phase被執行時,實際執行的都是被繫結到該phase的goal。

                2.goal與goal之間是獨立的。因此單獨執行一個goal不會導致其他goal被執行。

                goal可以通俗理解為一個專案。

                4.4 生命週期和phase的關係

                clean生命週期每套生命週期都由一組階段(Phase)組成,我們平時在命令列輸入的命令總會對應於一個特定的階段。比如,執行mvn clean ,這個的clean是Clean生命週期的一個階段。有Clean生命週期,也有clean階段。Clean生命週期一共包含了三個階段:

                1.pre-clean 執行一些需要在clean之前完成的工作

                2.clean 移除所有上一次構建生成的檔案

                3.post-clean 執行一些需要在clean之後立刻完成的工作

                "mvn clean" 中的clean就是上面的clean,在一個生命週期中,執行某個階段的時候,它之前的所有階段都會被執行,也就是說,"mvn clean"等同於 mvn pre-clean clean ,如果我們執行 mvn post-clean ,那麼 pre-clean,clean 都會被執行。這是Maven很重要的一個規則,可以大大簡化命令列的輸入

                執行phase實際執行的是goal。如果一個phase沒有繫結goal,那這個phase就不會被執行。

                <plugin>
                  <groupId>com.mycompany.example</groupId>
                  <artifactId>display-maven-plugin</artifactId>
                  <version>1.0</version>
                  <executions>
                    <execution>
                      <phase>process-test-resources</phase>
                      <goals>
                        <goal>time</goal>
                      </goals>
                    </execution>
                  </executions>
                </plugin>

                一個生命週期包含一些列的步驟,當執行生命週期的時候,會把所有的步驟執行一次

                官方文件:

                http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

                http://maven.apache.org/ref/3.3.9/maven-core/lifecycles.html

                5、idea maven的配置

                POM 中可以指定以下配置:

                • 專案依賴 dependencies
                • 外掛 plugins
                • 執行目標
                • 專案構建 profile
                • 專案版本
                • 專案開發者列表
                • 相關郵件列表資訊

                6、POM有2個很重要的關係:聚合、繼承

                一、聚合

                如果我們想一次構建多個專案模組,那我們就需要對多個專案模組進行聚合

                1.聚合配置程式碼

                <modules>
                      <module>模組一</module>
                      <module>模組二</module>
                      <module>模組三</module>
                </modules>

                  例如:對專案的Hello、HelloFriend、MakeFriends這三個模組進行聚合

                <modules>
                      <module>../Hello</module>  
                      <module>../HelloFriend</module>        
                      <module>../MakeFriends</module>
                </modules>

                其中module的路徑為相對路徑。

                二、繼承

                  繼承為了消除重複的配置,我們把很多相同的配置提取出來,例如:grouptId,version,相同的依賴包等。

                繼承配置程式碼:

                <parent>  
                         <groupId>me.gacl.maven</groupId>
                         <artifactId>ParentProject</artifactId>
                         <version>0.0.1-SNAPSHOT</version>
                         <relativePath>../ParentProject/pom.xml</relativePath>  
                </parent>

                Idea 中可以新建一個maven專案,然後刪光資料夾,只留一個pom.xml,然後新增模組,選擇繼承。

                圖片

                7、Maven 中的 profile

                • Maven 中有一個概念叫做:profile,它主要是為了解決不同環境所需的不同變數、配置等問題。比如我們內網開發的配置,埠配置等是和生產環境不同的,這個時候就需要區分。
                • 有了 profile,可以根據啟用的條件,啟動不同條件下的配置資訊。
                • profile 是可以有多個的,也可以同時啟用多個 profile,方便自由組合。
                <profiles>
                       <profile>
                           <!--不同環境Profile的唯一id-->
                           <!--開發環境-->
                           <id>dev</id>
                           <properties>
                               <!--profiles.active是自定義的欄位(名字隨便起),自定義欄位可以有多個-->
                               <profiles.active>dev</profiles.active>
                           </properties>
                       </profile>
                       <profile>
                           <!--線上環境-->
                           <id>prod</id>
                           <properties>
                               <profiles.active>prod</profiles.active>
                           </properties>
                           <activation>
                               <activeByDefault>true</activeByDefault>
                           </activation>
                       </profile>
                   </profiles>

                圖片

                Idea 中會顯示配置的兩個profile ,可以選擇啟用

                圖片

                pom檔案裡的配置為

                <build>
                       <resources>
                           <resource>
                               <directory>src/main/resources/</directory>
                               <!--先排除掉兩個資料夾-->
                               <excludes>
                                   <exclude>dev/*</exclude>
                                   <exclude>prod/*</exclude>
                               </excludes>
                               <includes>
                                   <!--如果有其他定義通用檔案,需要包含進來-->
                                   <!--<include>messages/*</include>-->
                               </includes>
                           </resource>
                           <resource>
                               <!--這裡是關鍵!根據不同的環境,把對應資料夾裡的配置檔案打包-->
                               <directory>src/main/resources/${profiles.active}</directory>
                           </resource>
                       </resources>
                   </build>
                  <profiles>
                       <profile>
                           <!--不同環境Profile的唯一id-->
                           <!--開發環境-->
                           <id>dev</id>
                           <properties>
                               <!--profiles.active是自定義的欄位(名字隨便起),自定義欄位可以有多個-->
                               <profiles.active>dev</profiles.active>
                           </properties>
                       </profile>
                       <profile>
                           <!--線上環境-->
                           <id>prod</id>
                           <properties>
                               <prwww.cppcns.comofiles.active>prod</profiles.active>
                           </properties>
                           <activation>
                               <activeByDefault>true</activeByDefault>
                           </activation>
                       </profile>
                   </profiles>

                8、maven 外掛

                Maven的核心僅僅定義了抽象的生命週期,具體的任務都是交由外掛完成的。

                每個外掛都能實現多個功能,每個功能就是一個外掛目標goal。

                Maven的生命週期與外掛目標相互繫結,以完成某個具體的構建任務,例如compile就是外掛maven-compiler-plugin的一個外掛目標。

                常用外掛:

                maven-antrun-plugin maven-archetype-plugin maven-assembly-plugin maven-dependency-plugin maven-enforcer-plugin maven-help-plugin maven-release-plugin maven-resources-plugin maven-surefire-plugin build-helper-maven-plusxKmFgin exec-maven-plugin jetty-maven-plugin versions-maven-plugin

                9、環境變數

                ${basedir}表示專案根目錄,即包含pom.xml檔案的目錄;

                ${version}表示專案版本;

                ${project.basedir}同${basedir};

                ${project.baseUri}表示專案檔案地址;

                ${maven.build.timestamp}表示專案構件開始時間;

                ${maven.build.timestamp.format}表示屬性${maven.build.timestamp}的展示格式,預設值為yyyyMMdd-HHmm,可自定義其格式,其型別可參考.text.SimpleDateFormat。

                ${project.build.directory}表示主原始碼路徑;

                ${project.build.sourceEncoding}表示主原始碼的編碼格式;

                ${project.build.sourceDirectory}表示主原始碼路徑;

                ${project.build.finalName}表示輸出檔名稱;

                ${project.version}表示專案版本,與${version}相同;

                ${project.xxx} 當前pom檔案的任意節點的內容

                ${env.xxx} 獲取系統環境變數。

                ${settings.xxx} 指代了settings.xml中對應元素的值。

                10、Maven 依賴衝突的2個方法

                1.統一版本

                使用dependencyManagement 進行版本鎖定,dependencyManagement可以統一管理專案的版本號,確保應用的各個專案的依賴和版本一致。

                如果我們專案中只想使用spring core 5.2.0的包,pom.xml可以改為如下

                <dependencyManagement>
                       <dependenciehttp://www.cppcns.coms>
                           <dependency>
                               <groupId>org.springframework</groupId>
                               <artifactId>spring-core</artifactId>
                               <version>5.2.0.RELEASE</version>
                           </dependency>
                       </dependencies>
                   </dependencyManagement>
                   <dependencies>
                       <dependency>
                           <groupId>org.springframework</groupId>
                           <artifactId>spring-context</artifactId>
                           <version>5.2.7.RELEASE</version>
                       </dependency>
                       <dependency>
                           <groupId>org.springframework</groupId>
                           <artifactId>spring-aop</artifactId>
                           <version>5.2.0.RELEASE</version>
                       </dependency>
                   </dependencies>

                2.排除依賴

                依賴查詢的兩個原則:

                使用路徑近者優先原則:直接依賴級別高於傳遞依賴。

                使用第一宣告者優先原則:誰先定義的就用誰的傳遞依賴,即在pom.xml檔案自上而下,先宣告的jar座標,就先引用該jar的傳遞依賴。

                Idea 可以安裝maven helper外掛,解決衝突。

                maven helper外掛安裝成功,點開pom.xml會發現多了一個Dependency Analyzer檢視,如下上面按鈕的圖示含義如下

                Conflicts(檢視衝突)

                All Dependencies as List(列表形式檢視所有依賴)

                All Dependencies as Tree(樹形式檢視所有依賴)

                上圖說明有3個jar存在衝突,點選衝突的jar,可以檢視和哪個jar產生衝突,如下圖

                圖片

                點開pom.xml,切換到Dependency Analyzer檢視,選擇All Dependencies as Tree,點選要排除的jar,右鍵會出現Execlude選項,如下

                圖片

                11、scope

                scope取值 有效範圍(compile,runtime,test) 依賴傳遞 例子
                compile all spring-core
                provided compile,test servlet-api
                runtime runtime,test JDBC驅動
                test test JUnit
                system compile,test

                compile :為預設的依賴有效範圍。如果在定義依賴關係的時候,沒有明確指定依賴有效範圍的話,則預設採用該依賴有效範圍。此種依賴,在編譯、執行、測試時均有效。

                provided :在編譯、測試時有效,但是在執行時無效。例如:servlet-api,執行專案時,容器已經提供,就不需要Maven重複地引入一遍了。

                runtime :在執行、測試時有效,但是在編譯程式碼時無效。例如:JDBC驅動實現,專案程式碼編譯只需要JDK提供的JDBC介面,只有在測試或執行專案時才需要實現上述介面的具體JDBC驅動。

                test :只在測試時有效,例如:JUnit。

                system :在編譯、測試時有效,但是在執行時無效。和provided的區別是,使用system範圍的依賴時必須通過systemPath元素顯式地指定依賴檔案的路徑。由於此類依賴不是通過Maven倉庫解析的,而且往往與本機系統繫結,可能造成構建的不可移植,因此應該謹慎使用。systemPath元素可以引用環境變數。

                總結:

                Maven是開發中常用的工具,很重要,所以儘可能的掌握。

                本篇文章就到這裡了,希望能給你帶來幫助,也希望您能夠多多關注我們的更多內容!