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

  • 2020 年 1 月 13 日
  • 筆記

記得,剛工作的時候我連 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 的存儲地址,默認是 當前用戶名.m2repository ,我建議改個好記的地方,後面方便檢查包有沒下載到本地。打開 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 詳細命令參考:https://www.jianshu.com/p/ee7bc34d7ccc

創建 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 標籤了,詳細介紹請看:

  • pom 標籤介紹參考:https://www.runoob.com/maven/maven-pom.html

項目打包到本地倉庫

由於項目是 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 中央倉庫查詢:

  • maven 中央倉庫:https://mvnrepository.com/

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 聚合工程

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

  • idea 搭建 maven 聚合工程參考:https://www.cnblogs.com/limn/p/9363416.html

-END-

如果看到這裡,你喜歡這篇文章的話,幫忙"轉發"或者點個"在看",行嗎?祝你們 2020 暴富。微信搜索「一個優秀的廢人」,關注後回復「1024」送你一套完整的 java 教程。