Maven 教程之入門指南

靜默虛空發表於2019-04-16

:notebook: 本文已歸檔到:「blog

簡介

Maven 是什麼

Maven 是一個專案管理工具。它負責管理專案開發過程中的幾乎所有的東西。

  • 版本 - maven 有自己的版本定義和規則。
  • 構建 - maven 支援許多種的應用程式型別,對於每一種支援的應用程式型別都定義好了一組構建規則和工具集。
  • 輸出物管理 - maven 可以管理專案構建的產物,並將其加入到使用者庫中。這個功能可以用於專案組和其他部門之間的交付行為。
  • 依賴關係 - maven 對依賴關係的特性進行細緻的分析和劃分,避免開發過程中的依賴混亂和相互汙染行為
  • 文件和構建結果 - maven 的 site 命令支援各種文件資訊的釋出,包括構建過程的各種輸出,javadoc,產品文件等。
  • 專案關係 - 一個大型的專案通常有幾個小專案或者模組組成,用 maven 可以很方便地管理。
  • 移植性管理 - maven 可以針對不同的開發場景,輸出不同種類的輸出結果。

Maven 的生命週期

maven 把專案的構建劃分為不同的生命週期(lifecycle)。粗略一點的話,它這個過程(phase)包括:編譯、測試、打包、整合測試、驗證、部署。maven 中所有的執行動作(goal)都需要指明自己在這個過程中的執行位置,然後 maven 執行的時候,就依照過程的發展依次呼叫這些 goal 進行各種處理。

這個也是 maven 的一個基本排程機制。一般來說,位置稍後的過程都會依賴於之前的過程。當然,maven 同樣提供了配置檔案,可以依照使用者要求,跳過某些階段。

Maven 的標準工程結構

Maven 的標準工程結構如下:

|-- pom.xml(maven的核心配置檔案)
|-- src
|-- main
	|-- java(java原始碼目錄)
	|-- resources(資原始檔目錄)
|-- test
    |-- java(單元測試程式碼目錄)
|-- target(輸出目錄,所有的輸出物都存放在這個目錄下)
    |-- classes(編譯後的class檔案存放處)
複製程式碼

Maven 的"約定優於配置"

所謂的"約定優於配置",在 maven 中並不是完全不可以修改的,他們只是一些配置的預設值而已。但是除非必要,並不需要去修改那些約定內容。maven 預設的檔案存放結構如下:

每一個階段的任務都知道怎麼正確完成自己的工作,比如 compile 任務就知道從 src/main/java 下編譯所有的 java 檔案,並把它的輸出 class 檔案存放到 target/classes 中。

對 maven 來說,採用"約定優於配置"的策略可以減少修改配置的工作量,也可以降低學習成本,更重要的是,給專案引入了統一的規範。

Maven 的版本規範

maven 使用如下幾個要素來唯一定位某一個輸出物:

  • groupId - 團體、組織的識別符號。團體標識的約定是,它以建立這個專案的組織名稱的逆向域名(reverse domain name)開頭。一般對應著 JAVA 的包的結構。例如 org.apache
  • artifactId - 單獨專案的唯一識別符號。比如我們的 tomcat, commons 等。不要在 artifactId 中包含點號(.)。
  • version - 一個專案的特定版本。
  • packaging - 專案的型別,預設是 jar,描述了專案打包後的輸出。型別為 jar 的專案產生一個 JAR 檔案,型別為 war 的專案產生一個 web 應用。

maven 有自己的版本規範,一般是如下定義 <major version><minor version><incremental version>-<qualifier> ,比如 1.2.3-beta-01。要說明的是,maven 自己判斷版本的演算法是 major,minor,incremental 部分用數字比 較,qualifier 部分用字串比較,所以要小心 alpha-2 和 alpha-15 的比較關係,最好用 alpha-02 的格式。

maven 在版本管理時候可以使用幾個特殊的字串 SNAPSHOT,LATEST,RELEASE。比如"1.0-SNAPSHOT"。各個部分的含義和處理邏輯如下說明:

  • SNAPSHOT - 這個版本一般用於開發過程中,表示不穩定的版本。
  • LATEST - 指某個特定構件的最新發布,這個釋出可能是一個釋出版,也可能是一個 snapshot 版,具體看哪個時間最後。
  • RELEASE - 指最後一個釋出版。

安裝

官網下載地址

Linux 環境安裝可以使用我寫一鍵安裝指令碼:github.com/dunwu/os-tu…

配置環境變數

注意:安裝 maven 之前,必須先確保你的機器中已經安裝了 JDK。

(1)解壓壓縮包(以 apache-maven-3.3.9-bin.zip 為例)

(2)新增環境變數 MAVEN_HOME,值為 apache-maven-3.3.9 的安裝路徑

Maven 教程之入門指南

(3)在 Path 環境變數的變數值末尾新增%MAVEN_HOME%\bin

(4)在 cmd 輸入 mvn –version,如果出現 maven 的版本資訊,說明配置成功。

Maven 教程之入門指南

本地倉儲配置

從中央倉庫下載的 jar 包,都會統一存放到本地倉庫中。我們需要配置本地倉庫的位置。

開啟 maven 安裝目錄,開啟 conf 目錄下的 setting.xml 檔案。

可以參照下圖配置本地倉儲位置。

Maven 教程之入門指南

第一個 Maven 工程

在 Intellij 中建立 Maven 工程

(1)建立 Maven 工程

依次點選 File -> New -> Project 開啟建立工程對話方塊,選擇 Maven 工程。

Maven 教程之入門指南

(2)輸入專案資訊

Maven 教程之入門指南

(3)點選 Intellij 側邊欄中的 Maven 工具介面,有幾個可以直接使用的 maven 命令,可以幫助你進行構建。

Maven 教程之入門指南

在 Eclipse 中建立 Maven 工程

(1)Maven 外掛

在 Eclipse 中建立 Maven 工程,需要安裝 Maven 外掛。

一般較新版本的 Eclipse 都會帶有 Maven 外掛,如果你的 Eclipse 中已經有 Maven 外掛,可以跳過這一步驟。

點選 Help -> Eclipse Marketplace,搜尋 maven 關鍵字,選擇安裝紅框對應的 Maven 外掛。

Maven 教程之入門指南

(2)Maven 環境配置

點選 Window -> Preferences

如下圖所示,配置 settings.xml 檔案的位置

Maven 教程之入門指南

(3)建立 Maven 工程

File -> New -> Maven Project -> Next,在接下來的視窗中會看到一大堆的專案模板,選擇合適的模板。

接下來設定專案的引數,如下:

Maven 教程之入門指南

groupId是專案組織唯一的識別符號,實際對應 JAVA 的包的結構,是 main 目錄裡 java 的目錄結構。

artifactId就是專案的唯一的識別符號,實際對應專案的名稱,就是專案根目錄的名稱。

點選 Finish,Eclipse 會建立一個 Maven 工程。

(4)使用 Maven 進行構建

Eclipse 中構建方式

在 Elipse 專案上右擊 -> Run As 就能看到很多 Maven 操作。這些操作和 maven 命令是等效的。例如 Maven clean,等同於 mvn clean 命令。

Maven 教程之入門指南

你也可以點選 Maven build,輸入組合命令,並儲存下來。如下圖:

Maven 教程之入門指南

Maven 命令構建方式

當然,你也可以直接使用 maven 命令進行構建。

進入工程所在目錄,輸入 maven 命令就可以了。

Maven 教程之入門指南

使用指導

如何新增外部依賴 jar 包

在 Maven 工程中新增依賴 jar 包,很簡單,只要在 POM 檔案中引入對應的<dependency>標籤即可。

參考下例:

<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/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.zp.maven</groupId>
  <artifactId>MavenDemo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>MavenDemo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <junit.version>3.8.1</junit.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.12</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>
複製程式碼

<dependency> 標籤最常用的四個屬性標籤:

  • <groupId> - 專案組織唯一的識別符號,實際對應 JAVA 的包的結構。
  • <artifactId> - 專案唯一的識別符號,實際對應專案的名稱,就是專案根目錄的名稱。
  • <version> - jar 包的版本號。可以直接填版本數字,也可以在 properties 標籤中設定屬性值。
  • <scope> - jar 包的作用範圍。可以填寫 compile、runtime、test、system 和 provided。用來在編譯、測試等場景下選擇對應的 classpath。

如何尋找 jar 包

可以在 mvnrepository.com/ 站點搜尋你想要的 jar 包版本

例如,想要使用 log4j,可以找到需要的版本號,然後拷貝對應的 maven 標籤資訊,將其新增到 pom .xml 檔案中。

如何使用 Maven 外掛(Plugin)

要新增 Maven 外掛,可以在 pom.xml 檔案中新增 <plugin> 標籤。

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.3</version>
      <configuration>
        <source>1.7</source>
        <target>1.7</target>
      </configuration>
    </plugin>
  </plugins>
</build>
複製程式碼

<configuration> 標籤用來配置外掛的一些使用引數。

如何一次編譯多個工程

假設要建立一個父 maven 工程,它有兩個子工程:my-app 和 my-webapp:

+- pom.xml
+- my-app
| +- pom.xml
| +- src
|   +- main
|     +- java
+- my-webapp
| +- pom.xml
| +- src
|   +- main
|     +- webapp
複製程式碼

app 工程的 pom.xml 如下,重點在於在 modules 中引入兩個子 module:

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>
 
  <modules>
    <module>my-app</module>
    <module>my-webapp</module>
  </modules>
</project>
複製程式碼

選擇編譯 XXX 時,會依次對它的所有 Module 執行相同操作。

常用 Maven 外掛

更多詳情請參考:maven.apache.org/plugins/

maven-antrun-plugin

maven-antrun-plugin 能讓使用者在 Maven 專案中執行 Ant 任務。使用者可以直接在該外掛的配置以 Ant 的方式編寫 Target, 然後交給該外掛的 run 目標去執行。在一些由 Ant 往 Maven 遷移的專案中,該外掛尤其有用。此外當你發現需要編寫一些自定義程度很高的任務,同時又覺 得 Maven 不夠靈活時,也可以以 Ant 的方式實現之。maven-antrun-plugin 的 run 目標通常與生命週期繫結執行。

maven-archetype-plugin

Archtype 指專案的骨架,Maven 初學者最開始執行的 Maven 命令可能就是mvn archetype:generate,這實際上就是讓 maven-archetype-plugin 生成一個很簡單的專案骨架,幫助開發者快速上手。可能也有人看到一些文件寫了mvn archetype:create, 但實際上 create 目標已經被棄用了,取而代之的是 generate 目標,該目標使用互動式的方式提示使用者輸入必要的資訊以建立專案,體驗更好。 maven-archetype-plugin 還有一些其他目標幫助使用者自己定義專案原型,例如你由一個產品需要交付給很多客戶進行二次開發,你就可以為 他們提供一個 Archtype,幫助他們快速上手。

maven-assembly-plugin

maven-assembly-plugin 的用途是將專案打包,該包可能包含了專案的可執行檔案、原始碼、readme、平臺指令碼等等。 maven-assembly-plugin 支援各種主流的格式如 zip、tar.gz、jar 和 war 等,具體打包哪些檔案是高度可控的,例如使用者可以 按檔案級別的粒度、檔案集級別的粒度、模組級別的粒度、以及依賴級別的粒度控制打包,此外,包含和排除配置也是支援的。maven-assembly- plugin 要求使用者使用一個名為assembly.xml的後設資料檔案來表述打包,它的 single 目標可以直接在命令列呼叫,也可以被繫結至生命週期。

maven-dependency-plugin

maven-dependency-plugin 最大的用途是幫助分析專案依賴,dependency:list能夠列出專案最終解析到的依賴列表,dependency:tree能進一步的描繪專案依賴樹,dependency:analyze可以告訴你專案依賴潛在的問題,如果你有直接使用到的卻未宣告的依賴,該目標就會發出警告。maven-dependency-plugin 還有很多目標幫助你操作依賴檔案,例如dependency:copy-dependencies能將專案依賴從本地 Maven 倉庫複製到某個特定的資料夾下面。

maven-enforcer-plugin

在一個稍大一點的組織或團隊中,你無法保證所有成員都熟悉 Maven,那他們做一些比較愚蠢的事情就會變得很正常,例如給專案引入了外部的 SNAPSHOT 依賴而導致構建不穩定,使用了一個與大家不一致的 Maven 版本而經常抱怨構建出現詭異問題。maven-enforcer- plugin 能夠幫助你避免之類問題,它允許你建立一系列規則強制大家遵守,包括設定 Java 版本、設定 Maven 版本、禁止某些依賴、禁止 SNAPSHOT 依賴。只要在一個父 POM 配置規則,然後讓大家繼承,當規則遭到破壞的時候,Maven 就會報錯。除了標準的規則之外,你還可以擴充套件該插 件,編寫自己的規則。maven-enforcer-plugin 的 enforce 目標負責檢查規則,它預設繫結到生命週期的 validate 階段。

maven-help-plugin

maven-help-plugin 是一個小巧的輔助工具,最簡單的help:system可以列印所有可用的環境變數和 Java 系統屬性。help:effective-pomhelp:effective-settings最 為有用,它們分別列印專案的有效 POM 和有效 settings,有效 POM 是指合併了所有父 POM(包括 Super POM)後的 XML,當你不確定 POM 的某些資訊從何而來時,就可以檢視有效 POM。有效 settings 同理,特別是當你發現自己配置的 settings.xml 沒有生效時,就可以用help:effective-settings來驗證。此外,maven-help-plugin 的 describe 目標可以幫助你描述任何一個 Maven 外掛的資訊,還有 all-profiles 目標和 active-profiles 目標幫助檢視專案的 Profile。

maven-release-plugin

maven-release-plugin 的用途是幫助自動化專案版本釋出,它依賴於 POM 中的 SCM 資訊。release:prepare用來準備版本釋出,具體的工作包括檢查是否有未提交程式碼、檢查是否有 SNAPSHOT 依賴、升級專案的 SNAPSHOT 版本至 RELEASE 版本、為專案打標籤等等。release:perform則 是簽出標籤中的 RELEASE 原始碼,構建併發布。版本釋出是非常瑣碎的工作,它涉及了各種檢查,而且由於該工作僅僅是偶爾需要,因此手動操作很容易遺漏一 些細節,maven-release-plugin 讓該工作變得非常快速簡便,不易出錯。maven-release-plugin 的各種目標通常直接在 命令列呼叫,因為版本釋出顯然不是日常構建生命週期的一部分。

maven-resources-plugin

為了使專案結構更為清晰,Maven 區別對待 Java 程式碼檔案和資原始檔,maven-compiler-plugin 用來編譯 Java 程式碼,maven-resources-plugin 則用來處理資原始檔。預設的主資原始檔目錄是src/main/resources,很多使用者會需要新增額外的資原始檔目錄,這個時候就可以通過配置 maven-resources-plugin 來實現。此外,資原始檔過濾也是 Maven 的一大特性,你可以在資原始檔中使用*${propertyName}*形式的 Maven 屬性,然後配置 maven-resources-plugin 開啟對資原始檔的過濾,之後就可以針對不同環境通過命令列或者 Profile 傳入屬性的值,以實現更為靈活的構建。

maven-surefire-plugin

可能是由於歷史的原因,Maven 2.3 中用於執行測試的外掛不是 maven-test-plugin,而是 maven-surefire-plugin。其實大部分時間內,只要你的測試 類遵循通用的命令約定(以 Test 結尾、以 TestCase 結尾、或者以 Test 開頭),就幾乎不用知曉該外掛的存在。然而在當你想要跳過測試、排除某些 測試類、或者使用一些 TestNG 特性的時候,瞭解 maven-surefire-plugin 的一些配置選項就很有用了。例如 mvn test -Dtest=FooTest 這樣一條命令的效果是僅執行 FooTest 測試類,這是通過控制 maven-surefire-plugin 的 test 引數實現的。

build-helper-maven-plugin

Maven 預設只允許指定一個主 Java 程式碼目錄和一個測試 Java 程式碼目錄,雖然這其實是個應當儘量遵守的約定,但偶爾你還是會希望能夠指定多個 原始碼目錄(例如為了應對遺留專案),build-helper-maven-plugin 的 add-source 目標就是服務於這個目的,通常它被繫結到 預設生命週期的 generate-sources 階段以新增額外的原始碼目錄。需要強調的是,這種做法還是不推薦的,因為它破壞了 Maven 的約定,而且可能會遇到其他嚴格遵守約定的外掛工具無法正確識別額外的原始碼目錄。

build-helper-maven-plugin 的另一個非常有用的目標是 attach-artifact,使用該目標你可以以 classifier 的形式選取部分專案檔案生成附屬構件,並同時 install 到本地倉庫,也可以 deploy 到遠端倉庫。

exec-maven-plugin

exec-maven-plugin 很好理解,顧名思義,它能讓你執行任何本地的系統程式,在某些特定情況下,執行一個 Maven 外部的程式可能就是最簡單的問題解決方案,這就是exec:exec的 用途,當然,該外掛還允許你配置相關的程式執行引數。除了 exec 目標之外,exec-maven-plugin 還提供了一個 java 目標,該目標要求你 提供一個 mainClass 引數,然後它能夠利用當前專案的依賴作為 classpath,在同一個 JVM 中執行該 mainClass。有時候,為了簡單的 演示一個命令列 Java 程式,你可以在 POM 中配置好 exec-maven-plugin 的相關執行引數,然後直接在命令執行mvn exec:java 以檢視執行效果。

jetty-maven-plugin

在進行 Web 開發的時候,開啟瀏覽器對應用進行手動的測試幾乎是無法避免的,這種測試方法通常就是將專案打包成 war 檔案,然後部署到 Web 容器 中,再啟動容器進行驗證,這顯然十分耗時。為了幫助開發者節省時間,jetty-maven-plugin 應運而生,它完全相容 Maven 專案的目錄結構,能夠週期性地檢查原始檔,一旦發現變更後自動更新到內建的 Jetty Web 容器中。做一些基本配置後(例如 Web 應用的 contextPath 和自動掃描變更的時間間隔),你只要執行 mvn jetty:run ,然後在 IDE 中修改程式碼,程式碼經 IDE 自動編譯後產生變更,再由 jetty-maven-plugin 偵測到後更新至 Jetty 容器,這時你就可以直接 測試 Web 頁面了。需要注意的是,jetty-maven-plugin 並不是宿主於 Apache 或 Codehaus 的官方外掛,因此使用的時候需要額外 的配置settings.xml的 pluginGroups 元素,將 org.mortbay.jetty 這個 pluginGroup 加入。

versions-maven-plugin

很多 Maven 使用者遇到過這樣一個問題,當專案包含大量模組的時候,為他們集體更新版本就變成一件煩人的事情,到底有沒有自動化工具能幫助完成這件 事情呢?(當然你可以使用 sed 之類的文字操作工具,不過不在本文討論範圍)答案是肯定的,versions-maven- plugin 提供了很多目標幫助你管理 Maven 專案的各種版本資訊。例如最常用的,命令 mvn versions:set -DnewVersion=1.1-SNAPSHOT 就能幫助你把所有模組的版本更新到 1.1-SNAPSHOT。該外掛還提供了其他一些很有用的目標,display-dependency- updates 能告訴你專案依賴有哪些可用的更新;類似的 display-plugin-updates 能告訴你可用的外掛更新;然後 use- latest-versions 能自動幫你將所有依賴升級到最新版本。最後,如果你對所做的更改滿意,則可以使用 mvn versions:commit 提交,不滿意的話也可以使用 mvn versions:revert 進行撤銷。

常用 Maven 命令

更詳細命令說明請參考:maven.apache.org/guides/intr…

生命週期 階段描述
mvn validate 驗證專案是否正確,以及所有為了完整構建必要的資訊是否可用
mvn generate-sources 生成所有需要包含在編譯過程中的原始碼
mvn process-sources 處理原始碼,比如過濾一些值
mvn generate-resources 生成所有需要包含在打包過程中的資原始檔
mvn process-resources 複製並處理資原始檔至目標目錄,準備打包
mvn compile 編譯專案的原始碼
mvn process-classes 後處理編譯生成的檔案,例如對 Java 類進行位元組碼增強(bytecode enhancement)
mvn generate-test-sources 生成所有包含在測試編譯過程中的測試原始碼
mvn process-test-sources 處理測試原始碼,比如過濾一些值
mvn generate-test-resources 生成測試需要的資原始檔
mvn process-test-resources 複製並處理測試資原始檔至測試目標目錄
mvn test-compile 編譯測試原始碼至測試目標目錄
mvn test 使用合適的單元測試框架執行測試。這些測試應該不需要程式碼被打包或釋出
mvn prepare-package 在真正的打包之前,執行一些準備打包必要的操作。這通常會產生一個包的展開的處理過的版本(將會在 Maven 2.1+中實現)
mvn package 將編譯好的程式碼打包成可分發的格式,如 JAR,WAR,或者 EAR
mvn pre-integration-test 執行一些在整合測試執行之前需要的動作。如建立整合測試需要的環境
mvn integration-test 如果有必要的話,處理包併發布至整合測試可以執行的環境
mvn post-integration-test 執行一些在整合測試執行之後需要的動作。如清理整合測試環境。
mvn verify 執行所有檢查,驗證包是有效的,符合質量規範
mvn install 安裝包至本地倉庫,以備本地的其它專案作為依賴使用
mvn deploy 複製最終的包至遠端倉庫,共享給其它開發人員和專案(通常和一次正式的釋出相關)

使用引數

-Dmaven.test.skip=true: 跳過單元測試(eg: mvn clean package -Dmaven.test.skip=true)

常見問題

dependencies 和 dependencyManagement,plugins 和 pluginManagement 有什麼區別?

dependencyManagement 是表示依賴 jar 包的宣告,即你在專案中的 dependencyManagement 下宣告瞭依賴,maven 不會載入該依賴,dependencyManagement 宣告可以被繼承。

dependencyManagement 的一個使用案例是當有父子專案的時候,父專案中可以利用 dependencyManagement 宣告子專案中需要用到的依賴 jar 包,之後,當某個或者某幾個子專案需要載入該外掛的時候,就可以在子專案中 dependencies 節點只配置 groupId 和 artifactId 就可以完成外掛的引用。

dependencyManagement 主要是為了統一管理外掛,確保所有子專案使用的外掛版本保持一致,類似的還有 plugins 和 pluginManagement。

IDEA 修改 JDK 版本後編譯報錯

錯誤現象

修改 JDK 版本,指定 maven-compiler-plugin 的 source 和 target 為 1.8 。

然後,在 Intellij IDEA 中執行 maven 指令,報錯:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.0:compile (default-compile) on project apollo-common: Fatal error compiling: 無效的目標版本: 1.8 -> [Help 1]
複製程式碼

錯誤原因

maven 的 JDK 源與指定的 JDK 編譯版本不符。

排錯手段

  • 檢視 Project Settings

Project SDK 是否正確

Maven 教程之入門指南

SDK 路徑是否正確

Maven 教程之入門指南
  • 檢視 Settings > Maven 的配置

JDK for importer 是否正確

Maven 教程之入門指南

Runner 是否正確

Maven 教程之入門指南

重複引入依賴

在 Idea 中,選中 Module,使用 Ctrl+Alt+Shift+U,開啟依賴圖,檢索是否存在重複引用的情況。如果存在重複引用,可以將多餘的引用刪除。

如何打包一個可以直接執行的 Spring Boot jar 包

可以使用 spring-boot-maven-plugin 外掛

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <executions>
        <execution>
          <goals>
            <goal>repackage</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
複製程式碼

如果引入了第三方 jar 包,如何打包?

首先,要新增依賴

<dependency>
  <groupId>io.github.dunwu</groupId>
  <artifactId>dunwu-common</artifactId>
  <version>1.0.0</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/src/main/resources/lib/dunwu-common-1.0.0.jar</systemPath>
</dependency>
複製程式碼

接著,需要配置 spring-boot-maven-plugin 外掛:

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <executions>
        <execution>
          <goals>
            <goal>repackage</goal>
          </goals>
        </execution>
      </executions>
      <configuration>
        <includeSystemScope>true</includeSystemScope>
      </configuration>
    </plugin>
  </plugins>
</build>
複製程式碼

最佳實踐

通過 bom 統一管理版本

採用類似 spring-boot-dependencies 的方式統一管理依賴版本。

spring-boot-dependencies 的 pom.xml 形式:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<packaging>pom</packaging>

<!-- 省略 -->

<!-- 依賴包版本管理 -->
<dependencyManagement>
    <dependencies>
    <!-- 省略 -->
    </dependencies>
</dependencyManagement>

<build>
<!-- 外掛版本管理 -->
<pluginManagement>
    <plugins>
    <!-- 省略 -->
    </plugins>
</pluginManagement>
</build>
</project>
複製程式碼

其他專案引入 spring-boot-dependencies 來管理依賴版本的方式:

 <dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
複製程式碼

引用和引申