Maven 基礎(一) | 使用 Maven 的正確姿勢

一、什么是 Maven?

Maven 是一個項目管理工具,它的本質是一個項目對象模型(POM),體現在配置中就是我們常見的 pom.xml 文件,而這個 pom 文件就是 Maven 的核心,它管理了整個項目的生命周期。它主要做兩件事:

  • 項目構建:對項目進行編譯、打包、測試、部署以及上傳到私服倉庫等

  • 依賴管理:Maven 誕生時就提出了一個倉庫的概念,項目中用到的第三方 jar 包,我們在 pom.xml 中配置好依賴即可,Maven 會自動到它的官方中央倉庫下載這個 jar 包到我們的本地倉庫。

  • 中央倉庫地址:https://mvnrepository.com/

二、為什么要使用 Maven?

  • 方便依賴管理:Java 發展至今,生態非常完善。我們在項目中用到什么功能,網上一搜肯定有對應的 jar 包,各種功能就導致了各種 jar 包的引入,這些 jar 包之間可能會有依賴,可能會有版本沖突。而 Maven 的誕生解決了這些問題。

  • 構建多模塊項目:現在很多項目都是分了多個模塊,便于開發、也便于擴展。多模塊就意味著模塊之間會有各種依賴,我們運行某個模塊,可能這個模塊依賴了別的模塊。而 Maven 的一鍵構建項目幫我們解決了這個問題。

  • 方便移植:以前沒 maven 的時代,團隊協作要上傳、下載一大堆 jar 包導入項目,耗時、費力。而有了 maven ,我們只需要同步一下 pom 文件即可同步 jar 包。這是 maven 解決的第三個問題。

三、怎么使用 Maven?

3.1 Maven 的安裝

這個就不講了,網上很多資料。比如:https://www.cnblogs.com/KyleXu/p/9972042.html

3.2 Maven 的配置

Maven 的配置比較簡單,主要是修改 conf 文件夾下的 setting 文件。配置以下三個倉庫:

本地倉庫

項目依賴的 jar 包是需要下載到本地才能用的。本地倉庫就是從 maven 私服或者遠程倉庫下載的 jar 的存儲地址,默認是 當前用戶名\.m2\repository ,我建議改個好記的地方,后面方便檢查包有沒下載到本地。打開 setting.xml 搜索 localRepository 修改成自定義的地址。

<localRepository>D:\Repository</localRepository>

配置的位置,如下圖:

本地倉庫

私服倉庫

這個倉庫的話,一般就是公司內部使用的啦。用來存儲公司內部自己的 jar 包。打開 setting.xml 文件搜索 mirrors ,配置公司的鏡像地址即可。

<mirror>
    <id>nexus-repos</id>
    <mirrorOf>*</mirrorOf>
    <name>Team Nexus Repository</name>
    <url>http://127.0.0.1:8081/nexus/content/groups/public</url>
</mirror>

遠程倉庫

遠程倉庫就是一個 maven 官方維護的,包含大量 jar 包的倉庫。這個庫默認是 maven 官方的,但是下載非常慢。所以業界典范阿里巴巴也推出了一個國內的鏡像,我們一般把遠程倉庫配成阿里的鏡像地址,就可以快速地下載 jar包啦。和私服倉庫一樣,遠程倉庫也是配置在 <mirrors> 標簽內。

<mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>
</mirror>

配置的位置,如下圖:

遠程倉庫

有人可能問了,配置那么多個倉庫。究竟 jar 從哪個下載的呀?都把我搞糊涂了,別急,我花了個流程圖,它的查找順序是這樣的:本地不需要網絡,優先從本地找;找不到,再去速度較高的內網私服找;然后才是速度稍低的外網遠程倉庫找。

maven 查找文件流程

3.3 Maven 的命令

常用命令

命令 含義 備注
mvn clean 清除 打包前,清空上一次的包
mvn compile 編譯 將 java 代碼編譯成 class 文件
mvn test 測試 運行單元測試
mvn install 安裝到本地 安裝到本地倉庫,一般是 jar 包
mvn package 打包 一般會在 target 目錄下生成包,jar 或 war
mvn deploy 上傳 上傳到私服,需在 setting.xml 文件配置私服倉庫以及賬號密碼

以上就是 maven 常用的命令,要注意的是:很少情況下我們只運行其中一個命令,都是組合運行的。比如打包到本地,打包前得清空原有的包吧?那組合起來就是 mvn clean + mvn install

當然,在 IDEA 中開發 maven 項目,我們并不需要手打。只需點擊對應命令即可(也可以按住 ctrl 選中多個命令一起運行)

maven 操作

總而言之,根據自己的需求來選擇打包命令。還有其他的命令請見:

創建 maven 項目

現在一般都是配合 idea 新建 maven 項目了,這個命令用得很少,但我們還是得知道一下:生成 maven 項目的原理是,依賴一個插件 maven-archetype-plugin,然后這個插件自帶一些 archetype 模版,也可以說成項目的骨架。其中:-DgroupId-DartifactId填寫自己想好的項目坐標,一般 -DgroupId是公司名的翻轉,比如 com.google-DartifactId 就是項目的名稱了。最重要的是-DarchetypeArtifactId,他指定了創建的骨架。

mvn archetype:generate -DgroupId=com.nasus -DartifactId=maven-test -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
創建 maven 項目成功

點進去,只有 src文件夾和 pom.xml文件:src 是最重要的目錄,代碼和測試用例以及資源都是放在這里的,對于 maven 項目而言,pom.xml 也是必不可少的。

項目結構

idea 打開的項目結構是這樣的:

idea 打開

pom.xml 的內容:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <!--聲明項目描述符遵循哪一個 POM 模型版本,上面的 xsd 規范定義了這個版本,默認就行,不需要修改,不可刪除-->
    <modelVersion>4.0.0</modelVersion>

    <!--團體唯一標識符-->
    <groupId>com.nasus</groupId>

    <!--項目唯一標識符定位這個包-->
    <artifactId>maven-test</artifactId>

    <!--打包類型-->
    <packaging>jar</packaging>

    <!--打包版本-->
    <version>1.0-SNAPSHOT</version>

    <!--包名-->
    <name>maven-test</name>

    <!--不用管,刪掉也行-->
    <url>http://maven.apache.org</url>

    <!--項目需要依賴的 jar 包-->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

由于篇幅原因,這里就不詳細講具體的 pom.xml 標簽了,詳細介紹請看:

項目打包到本地倉庫

由于項目是 java 項目,在打包前,我們要在 pom.xml 中配置項目的 JDK 版本以及 maven 插件版本,在 <dependencies> 標簽前加入項目屬性配置,完整配置如下:

    <!--項目屬性,在 <dependencies> 前加-->
    <properties>
        <!-- JDK編譯版本 -->
        <java.version>1.8</java.version>
        <!-- 項目編碼 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- JDK編譯版本 -->
        <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>
    <!--項目需要依賴的 jar 包-->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

選擇命令,這里我選了 clean、compile、package

選擇命令

點擊綠色執行按鈕,在 target 目錄下生成 maven-test-1.0.SNAPSHOT.jar:

打包結果

跳過單元測試

在開發中,我們經常需要本地測試,而這時我們是不需要跑單元測試的。所以,我們可以跳過單元測試:選中 test,點擊紅框按鈕即可。

跳過單元測試

手動打 jar 包到本地倉庫

手動打 jar 包的應用場景是:開發公司舊項目,當找不到依賴的 jar 源碼,依賴的 jar 又沒有上傳到倉庫,只有在同事電腦的本地倉庫有一個 jar 包時,我們可以直接運行這條命令把 jar 包打到我們電腦本地倉庫,愉快的使用起來。

mvn install:install-file -Dfile=jar包的路徑 -DgroupId=gruopId中的內容 -DartifactId=actifactId的內容 -Dversion=version的內容 -Dpackaging=jar

四、maven 依賴管理

maven 通過 pom.xml 來進行依賴管理,我們用它來描述項目的依賴屬性。可以把它看作是 maven 項目的地圖,它描述了 jar 包的坐標、版本以及依賴關系等。如果不確定你想要引入 jar 的坐標怎么寫,可以上 maven 中央倉庫查詢:

4.1 maven 坐標

maven 的第三方依賴都在 <dependencies>標簽內定義,該標簽下的 <dependency> 包裹的內容就是一個 jar 的坐標,如下 pom 就引入了 junitcglib 兩個 jar 。下面就說一下每個坐標的標簽都代表什么。

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.3.0</version>
    </dependency>
</dependencies>
  • dependencies

在 dependencies 標簽中,添加項目需要的 jar 所對應的 maven 坐標。

  • dependency

一個 dependency 標簽表示一個坐標,也就是一個 jar,在 pom 中引入一個 jar 可以這樣寫:

<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
</dependency>
  • groupId

公司、團體、個人開發者的唯一標識符,maven 約束它以創建這個項目的組織名稱的逆向域名開頭,比如開發者的域名是 nasus.com 那他的唯一標識符就是 com.nasus

<!--團體唯一標識符-->
<groupId>com.nasus</groupId>
  • artifactId

項目唯一標識符,一個組織可能有多個項目,為了方便 maven 引入,maven 約定以項目名稱命名該標識符,比如我開發的 maven-test 項目。

<!--項目唯一標識符-->
<artifactId>maven-test</artifactId>
  • version

項目的版本。一個項目,可能會有多個版本。如果是正在開發的項目,我們可以給版本號加上一個 SNAPSHOT,表示這是一個快照版本。

什么是快照?

對于版本,如果 maven 以前下載過指定的版本文件,比如說 maven-test:1.0maven 將不會再從倉庫下載新的可用的 1.0 文件。若要下載更新的代碼,maven-test 的版本需要升到 1.1

快照是一種特殊的版本,指定了某個當前的開發進度的副本。不同于常規的版本,maven 每次構建都會在遠程倉庫中檢查新的快照。我們自己的模塊依賴了同事開發的模塊,正常來說,同事會每次發布更新代碼的快照到倉庫中。

新建項目的默認版本號就是快照版,比如上面用 maven 命令新建的 maven-test 項目:

SNAPSHOT

4.2 依賴范圍

  • scope

maven 項目不同的階段引入到 classpath 中的依賴是不同的,例如,編譯時,maven 會將與編譯相關的依賴引入 classpath 中,測試時,maven 會將測試相關的的依賴引入到 classpath 中,運行時,maven 會將與運行相關的依賴引入 classpath 中,而依賴范圍就是用來控制依賴于這三種 classpath 的關系。 如下圖所示:

依賴傳遞,圖:菜鳥教程

scope 表示依賴的范圍,它有 compile(編譯階段)、test(測試階段)、provided(供應階段)、runtime(運行階段)、system(系統階段)、import(導入階段) 六個可選值。其中 compile 是默認的。systemimport 用得少,不詳細講。

不同依賴的適用范圍不一樣,舉幾個最典型的栗子:

范圍 編譯有效 測試有效 運行時有效 打包有效 示例
compile spring-core
test junit
provided javax.servlet-api
runtime JDBC驅動
  • compile: 編譯依賴范圍。如果沒有指定,就會默認使用該依賴范圍。使用此依賴范圍的 Maven 依賴,對于編譯、供應、測試、運行四種 classpath 都有效。比如 spring-core

  • provided: 已提供依賴范圍。使用此依賴范圍的 Maven 依賴,對于 編譯和測試 classpath 有效,但在運行時無效。典型的例子是 servlet-api 編譯和測試項目的時候需要該依賴,但在運行項目的時候,由于容器已經提供,就不需要 maven 重復地引入一遍:

<dependency>
     <groupId>javax.servlet</groupId>
     <artifactId>javax.servlet-api</artifactId>
     <version>3.1.0</version>
     <scope>provided</scope>
</dependency>
  • test: 單元測試依賴范圍,只在測試的時候生效,所以可以設置它的 scope 為 test,這樣,當項目打包發布時,單元測試的依賴就不會跟著發布。比如:
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>
  • runtime: 運行時依賴范圍。對于測試和運行 classpath 有效,但在編譯主代碼時無效。典型的例子是 JDBC 驅動實現,項目主代碼的編譯只需要 JDK 提供的 JDBC 接口,只有在執行測試或者運行項目的時候才需要實現上述接口的具體 JDBC 驅動。所以,我們使用 JDBD 驅動時,可以定義成以下樣例:
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.12</version>
    <scope>runtime</csope>
</dependency>

4.3 排除依賴

如下 xml,原來的定義中已引入 commons-net 依賴,而 hermes-ftp 中又依賴了 commons-net,為避免版本沖突,我們可以排除 hermes-ftp 中的 commons-net 依賴。

<dependency>
      <groupId>commons-net</groupId>
      <artifactId>commons-net</artifactId>
      <version>3.6</version>
</dependency>
<dependency>
    <groupId>com.nasus.greece.jupiter</groupId>
    <artifactId>hermes-ftp</artifactId>
    <version>1.1.0-SNAPSHOT</version>
    <!--排除 commons-net 依賴-->
    <exclusions>
        <exclusion>
            <artifactId>commons-net</artifactId>
            <groupId>commons-net</groupId>
        </exclusion>
   </exclusions>
</dependency>

4.4 依賴傳遞

假設有如下項目關系:WebMavenDemo 項目依賴 JavaMavenService1JavaMavenService1 項目依賴 JavaMavenService2

項目關系

pom.xml 文件配置好依賴關系后,必須首先 mvn install 后,依賴的 jar 包才能使用。比如:

  • WebMavenDemopom.xml 文件想能編譯通過,JavaMavenService1 必須 mvn install
  • JavaMavenServicepom.xml 文件想能編譯通過,JavaMavenService2 必須 mvn install

傳遞性:

傳遞性

假設我們現在 JavaMavenService2 增加 spring-core ,那就會發現WebMavenDemoJavaMavenService1 也會自動的增加了這個jar包,這就是依賴的傳遞性。

注意:非 compile 范圍的依賴是不能傳遞的。

  • 來源:cnblogs.com/hzg110/p/6936101.html

4.5 統一管理依賴版本

在上面介紹 pom 文件時,我們講過 properties 標簽,它還有一個作用就是限定依賴的 jar 包版本,它常用在父項目中指定版本號,那么子項目用到該包就避免了版本不一致造成的依賴沖突,它的寫法是這樣的:

統一管理版本

五、build 配置

maven 打 war 包時,可能需要一些額外的配置,請參看以下 xml 文件:

<build>
  <!-- 項目的名字 -->
  <finalName>maven-test</finalName>
  <!-- 描述項目中資源的位置 -->
  <resources>
    <!-- 自定義資源1 -->
    <resource>
      <!-- 資源目錄 -->
      <directory>src/main/java</directory>
      <!-- 包括哪些文件參與打包 -->
      <includes>
        <include>**/*.xml</include>
      </includes>
      <!-- 排除哪些文件不參與打包 -->
      <excludes>
        <exclude>**/*.txt</exclude>
          <exclude>**/*.doc</exclude>
      </excludes>
    </resource>
  </resources>
  <!-- 設置構建時候的插件 -->
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>2.1</version>
      <configuration>
        <!-- 源代碼編譯版本 -->
        <source>1.8</source>
        <!-- 目標平臺編譯版本 -->
        <target>1.8</target>
      </configuration>
    </plugin>
    <!-- 資源插件(資源的插件) -->  
    <plugin>  
      <groupId>org.apache.maven.plugins</groupId>  
      <artifactId>maven-resources-plugin</artifactId>  
      <version>2.1</version>  
      <executions>  
        <execution>  
          <phase>compile</phase>  
        </execution>  
      </executions>  
      <configuration>  
        <encoding>UTF-8</encoding>  
      </configuration> 
    </plugin>
    <!-- war插件(將項目打成war包) -->  
    <plugin>  
      <groupId>org.apache.maven.plugins</groupId>  
      <artifactId>maven-war-plugin</artifactId>  
      <version>2.1</version>  
      <configuration>
        <!-- war包名字 -->  
        <warName>maven-test</warName>
      </configuration>  
    </plugin>  
  </plugins>
</build>

六、使用 idea 搭建 maven 聚合工程

這個網上很多資料,不講了。留個鏈接。

最后

如果看到這里,喜歡這篇文章的話,請轉發、點贊。微信搜索「一個優秀的廢人」,歡迎關注。

回復「1024」送你一套完整的 java、python、c++、go、前端、linux、算法、大數據、人工智能、小程序以及英語教程。

回復「電子書」送你 50+ 本 java 電子書。

編程語言
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容

  • 1. 定義 Maven 是一個項目管理工具,它包含了一個項目對象模型 (POM:Project Object Mo...
    魔笛使者閱讀 1,213評論 0 0
  • 主要內容 Maven 介紹 Maven 的使用 Maven 常用命令 idea 開發 maven 項目 1.1.1...
    AlexDing閱讀 420評論 0 0
  • Maven使用入門 1. Maven概述 Maven是什么?Maven項目對象模型(POM),可以通過一小段描述信...
    小小韓_小小紅閱讀 2,555評論 2 28
  • 簡介 概述 Maven 是一個項目管理和整合工具 Maven 為開發者提供了一套完整的構建生命周期框架 Maven...
    閩越布衣閱讀 4,321評論 6 39
  • 1: maven是什么? maven是Apache公司的開源項目,是一個服務于Java項目的自動化構建工具,用來管...
    覆水無言閱讀 411評論 0 0