一、pom 簡介
POM 是項目對象模型 (Project Object Model) 的簡稱, XML 格式,名稱為 pom.xml ,它是 Maven 項目的核心配置文件,該文件用於管理源代碼、配置文件、開發者的信息和角色、問題追蹤系統、組織信息、項目授權、項目的url、項目的依賴關系等等.事實上,在 Maven 的世界中,一個項目可以什么都沒有,甚至沒有代碼,但是必須包含 pom.xml 文件.並且一個 Maven 項目有且只有一個 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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 基本設置 The Basics -->
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<packaging>...</packaging>
<dependencies>...</dependencies>
<parent>...</parent>
<dependencyManagement>...</dependencyManagement>
<modules>...</modules>
<properties>...</properties>
<!-- 構建過程的設置 Build Settings -->
<build>...</build>
<reporting>...</reporting>
<!-- 項目信息設置 More Project Information -->
<name>...</name>
<description>...</description>
<url>...</url>
<inceptionYear>...</inceptionYear>
<licenses>...</licenses>
<organization>...</organization>
<developers>...</developers>
<contributors>...</contributors>
<!-- 環境設置 Environment Settings -->
<issueManagement>...</issueManagement>
<ciManagement>...</ciManagement>
<mailingLists>...</mailingLists>
<scm>...</scm>
<prerequisites>...</prerequisites>
<repositories>...</repositories>
<pluginRepositories>...</pluginRepositories>
<distributionManagement>...</distributionManagement>
<profiles>...</profiles>
</project>
我們這里就選擇一些比較常用的配置來說
三、pom 常用配置
1、坐標
坐標是一個項目的唯一標識符,可以通過坐標准確的定位到某一個具體的項目.有了坐標進行定位之后,如果其它的 Maven 項目想使用該項目生成的 jar 包,只需要通過坐標引入依賴即可
Maven 坐標是通過 groupId、artifactId、version 來共同定位的.
groupId: 組織 Id ,表示當前模塊所隸屬的項目.起名規范:一級域名(com、org).二級域名(公司名稱).項目名稱
artifactId: 模塊 Id, 表示一個項目中的某個模塊,例如商城項目里面的訂單模塊、用戶模塊、商品模塊...等等
version:當前的版本
為什么坐標需要三個元素才能定位呢?比如你自己的項目中需要使用某一個 jar 包,那么怎么找到這個 jar 包呢?這個時候你就需要使用 groupId 來定位這個 jar 包是屬於哪個公司的哪個項目,定位到了項目之后呢,你還需要使用 artifactId 定位到該項目的具體模塊,因為一個項目可以有很多的模塊,定位到了具體模塊之后呢,還需要使用 version 來定位具體的版本號,因為一個模塊可以進行迭代,如果不指定具體的版本號也就無法准確的定位,這個類似於地理里面只有通過東經和北緯才能准確定位一個地理位置一樣.
<!-- 組織 Id -->
<groupId>com.xiaomaomao.springAnalyse</groupId>
<!-- 模塊 Id -->
<artifactId>spring-ioc</artifactId>
<!-- 具體的版本號 -->
<version>1.0-SNAPSHOT</version>
2、全局變量 properties
properties: 全局屬性,一般情況下用於定義全局的 jar 包版本.僅僅是定義全局變量,不起其他作用.
應用場景:在實際項目中如果我們使用同一個公司的 jar 包, jar 包的版本號最好是保持一致,因為有時候 jar 包版本不一致的情況下,有可能會出現不同版本之間發生不兼容的錯誤, 我們這里就以 spring 為例,下面的這些依賴當中 spring-context、spring-webmvc 都是屬於 spring 的 jar 包,並且它們的版本號都是 4.3.11.RELEASE,突然有一天,項目經理興奮的告訴我,spring 推出了 5.0 版本,功能很強大,我們要升級版本,那么這個時候你就只能挨個的找到 spring 相關的依賴,一個一個的把它們升級到 5.0 版本,我們這里僅僅只有兩個 spring 相關的依賴,改起來比較快,可是如果你的項目里面使用了幾十個,甚至上百個 spring 的依賴呢?這個時候你挨個挨個的去替換,工作量比較大,並且還有可能一不留神改錯了,好不容易改完了,也沒有改錯,終於可以休息一下了,這個時候項目經理那個糟老頭子又來了,他告訴你 spring 5.0 有版本缺陷,我們還是改回原來的 4.3.11.RELEASE 版本吧,我想此時你是奔潰的,你就只能挨個挨個的將 spring 的依賴 jar 包一個一個的還原,好了,還原了,也改好了,終於沒事了,你冷不丁的冒出一個念頭,萬一項目經理又要我切換成其它的版本,工作量太大了,有沒有什么比較好的辦法呢?
答案是有的,我們就可以通過 properties 標簽來統一管理 jar 包的版本
<dependencies>
<!-- spring 基本依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<!-- spring-webmvc 依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<!-- juint 依賴 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- servlet-api 依賴 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
在 <properties> 標簽中定義一類 jar 包的版本,引入依賴的時候通過 ${標簽名} 的方式來控制版本
<properties>
<!--標簽名稱任意,但是最好是一個有意義的名稱-->
<spring-version>4.3.11.RELEASE</spring-version>
<junit-version>4.11</junit-version>
<javax.servlet-version>4.0.0</javax.servlet-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<!--使用 ${自定義的標簽} 來引入 properties 中定義的標簽里面的值-->
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet-version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
如果以后想統一切換 spring、junit 等 jar 包的版本,我們只需要在 properties 標簽中切換就可以了,再也不用去依賴中挨個挨個的替換 jar 包的版本了
3、dependency
dependency 標簽統一的定義在 dependencies 標簽中,它代表的意思是我們可以通過該標簽引入我們需要的相關 jar 包
3.1、如何查找一個 jar 包的地址?
Maven 依賴官網:https://mvnrepository.com/
3.1.1、進入官網,查找需要的 jar 包
3.1.2、選擇 jar 包版本
3.1.3、復制依賴到項目 pom.xml 中
3.2、如何查看引入的依賴
4、依賴的 scope 作用域
依賴的 scope 標簽表示的意思是依賴的使用范圍(也就是這個 jar 包在什么范圍內是可以使用的),scope 的取值有 compile、test、provided、runtime、system
4.1、compile
該依賴可以在整個項目中使用(是指代碼范圍, main 目錄和 test 目錄下都能使用這個依賴),參與打包部署.是 scope 的默認值.典型的例如: commonsfileupload
例如:我們修改 spring 核心依賴 spring-context 的 scope 為 test
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
<scope>test</scope>
</dependency>
在 main 目錄下使用就出現了報錯
在 test 目錄下使用就是正常的
4.2、test
該依賴只能在測試代碼中使用(是指代碼范圍,只能在 test 目錄下使用這個依賴),不參與打包部署.典型的例如: junit
4.3、provided
該依賴編寫源代碼時需要使用,因為當我們使用 Servlet 的時候,如果不添加 javax.servlet-api 依賴,就無法使用里面相關的 API,如果使用了編譯就會報錯,
provided 不參與打包部署.只是在編寫源碼的時候使用,為什么不參與打包部署呢?
因為我們的項目打包部署到服務器的時候,服務器會為我們提供 javax.servlet-api ,這里以 tomcat 為例,找到 tomcat 的安裝目錄,打開里面的 lib 目錄,在 tomcat 容器啟動的時候會為我們提供 servlet-api.jar ,那么我們項目中的 pom.xml 中就不需要再提供 servlet-api 這個依賴了
4.4、runtime
該依賴編寫代碼時不需要,運行時需要,參與打包部署.典型的例如數據庫驅動 mysql-connector-java
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
為什么編寫代碼時不需要呢?
jvm 運行期的時候通過反射加載數據庫驅動,完成例如注冊驅動、獲取連接、獲取 PrepareStatement 對象等,我們編寫代碼的時候只是在編譯期間,根本不會使用到數據庫驅動,項目最終打包部署的時候也是需要數據驅動的,否則你無法連接數據庫和操作 Sql 語句.
4.5、system
表示使用本地系統路徑下的 jar 包,需要和 systemPath 配合使用,典型的例如 Oracle 數據庫驅動: ojdbc.jar ,它是未授權 Maven 中央倉庫的(剛剛去 Maven 中央倉庫發現有,但是我們就假設它沒有被 Maven 中央倉庫錄入)
有些 jar 包可能因為授權的問題或者是一些個人的 jar 包,這些 jar 包不會被 Maven 中央倉庫錄入,這個時候如果我們想在項目中使用這些 jar 包的話,我們可以先將 jar 包下載先來,然后可以在 pom.xml 中配置指向本地某個 jar 包的路徑,引入相關的 jar 包
引入 Oracle 驅動之后就可以使用了,沒有出現報錯
其實吧,我覺得如果某些 jar 包 Maven 中央倉庫沒有錄入,我們可以將需要的 jar 包下載下來,然后上傳到私服中,通過左邊從私服中下載就可以了.
這里總結一下 scope 依賴范圍
對主程序是否有效 | 對測試程序是否有效 | 是否參與打包 | 是否參與部署 | 典型例子 | |
compile | 是 | 是 | 是 | 是 | spring-context |
test | 否 | 是 | 否 | 否 | junit |
provided | 是 | 是 | 否 | 否 | servlet-api、jsp-api |
runtime | 否 | 否 | 是 | 是 | mysql-connector-java |
system | - | - | - | - | - |
4.6、遠程倉庫 repositories
repositories:用來配置當前工程使用的遠程倉庫
依賴查找順序:本地倉庫--->當前工程 pom.xml 中配置的遠程倉庫--->用戶級別的 settings.xml 中配置的遠程倉庫----> 全局 settings.xml 中配置的遠程倉庫---->Maven 中央倉庫
應用場景:
如果有些 jar 包在 Maven 中央倉庫沒有,但是在其他倉庫(例如:阿里倉庫、spring 倉庫、mybatis 倉庫)里是有這個 jar 包的,例如 spring 新發布了一個版本,由於是剛發行的版本,性能不太穩定,這個時候 Maven 中央倉庫一般不會將這些 jar 包錄入,但是你就是想用 spring 最新的版本,那么可以在 pom.xml 中通過配置 repositories 從指定的某公司官方倉庫來獲取相應的 jar 包
<repositories>
<!-- 配置 spring 官方倉庫 -->
<repository>
<!-- 遠程倉庫唯一標識符 -->
<id>spring_repo</id>
<!-- 倉庫名稱,可以使用一個有意義的名稱命名 -->
<name>Private Repository</name>
<!-- spring 官方遠程倉庫地址 -->
<url>http://repo.spring.io/milestone</url>
<!-- 用於定位和排序構件的倉庫布局類型,它的取值有 default(默認)或 legacy(遺留) -->
<layout>default</layout>
<releases>
<!-- 是否開啟 release 或者 snapshots 的下載支持.默認值為 false ,表示不會從該中央倉庫下載快照版本的構件 -->
<enabled>true</enabled>
<!-- 用來配置 Maven 從遠程倉庫檢查更新的頻率,
默認是 daily,表示每天檢查一次;
never: 從不檢查更新;
always: 每次構建都檢查更新;
interval:X 每隔 X 分鍾檢查一次更新 -->
<updatePolicy>always</updatePolicy>
<!--用來配置 Maven 檢查檢驗和文件的策略,當構建被部署到Maven倉庫中時,會同時部署對於應用的檢驗和文件,
在下載構件的時候, Maven 會驗證校驗和文件
checksumPolicy 默認值是 warn ,會執行構建時輸出警告信息
fail:遇到校驗和錯誤就構件失敗
ignore:完全忽略校驗和錯誤 -->
<checksumPolicy>warn</checksumPolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
<!-- 配置 阿里 官方遠程倉庫 -->
<repository>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
4.7、插件 plugins
插件,就是一種工具.常見的如:清理插件 mavencleanplugin ,編譯插件 mavencompileplugin
插件和依賴的區別:插件是工具,偏向於開發環境.和項目功能、源碼、打包好的 jar 包沒有任何關系.插件和依賴的關系,類似於 IDEA 工具和上線的 jar 包.
Maven 的核心文件很小,主要的任務都是由插件來完成.定位到:%本地倉庫%\org\apache\maven\plugins ,可以看到一些下載好的插件
4.7.1、插件的目標 (Plugin Goals)
一個插件通常可以完成多個任務,每一個任務就叫做插件的一個目標.如執行 mvn install 命令時,調用的插件和執行的插件目標如下
4.7.2、將插件綁定到生命周期
Maven 的生命周期是抽象的,實際需要插件來完成任務,這一過程是通過將插件的目標 (goal) 綁定到生命周期的具體階段 (phase) 來完成的.
例如將 maven-compiler-plugin 插件的 compile 目標綁定到 default 生命周期的 compile 階段,完成項目的源代碼編譯.
Maven 對一些生命周期的階段(phase)默認綁定了插件目標,因為不同的項目有 jar、war、pom 等不同的打包方式,因此對應的有不同的綁定關系,其中針對 default 生命周期的 jar 包打包方式的綁定關系如下
第二列中,冒號后面即是綁定的插件目標,冒號前面是插件的前綴(prefix),是配置和使用插件的一種簡化方式.
4.7.3、自定義綁定
用戶可以根據需要將任何插件目標綁定到任何生命周期的階段, 例如將 maven-source-plugin 的 jar-no-fork 目標綁定到 default 生命周期的 package 階段, 這樣,以后在執行 mvn package 命令打包項目時,在 package 階段之后會執行源代碼打包,生成如 ehcache-core-2.5.0-sources.jar 形式的源碼包.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-source</id>
<!-- 要綁定到的生命周期的階段 -->
<phase>package</phase>
<goals>
<!-- 要綁定的插件的目標 -->
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
……
</build>
4.7.4、pom.xml 中配置插件
<build>
<plugins>
<plugin>
<!-- 在這里添加 clean 插件,可以替換掉之前插件的版本 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<!-- 一般 web 項目需要添加一個 tomcat 插件 -->
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<!-- 這里還可以配置 tomcat 的項目訪問 URL 和項目訪問端口 -->
<configuration>
<path>/xiaomaomao</path>
<port>8888</port>
</configuration>
</plugin>
</plugins>
</build>
這里有個很奇怪的現象,我使用 IDEA 幫我創建 Web 項目, IDEA 自動幫我下載了插件,其中 maven-clean-plugin 插件的版本是 3.1.0 ,我這里把插件的版本替換成了 3.0.0
然后看一下我們加入的 maven-tomcat 插件
五、超級 pom
當我們利用 IDEA 為我們創建工程的時候,我們沒有進行任何配置,為什么能下載各種插件呢?這是由於存在超級 pom 的原因,所有的 Maven 項目都要繼承超級 pom,里面有 Maven 默認的一些配置
超級 pom 存放位置: Maven 的安裝目錄\bin\maven-model-builder-3.6.0.jar\org\apache\maven\model\pom-4.0.0.xml
解壓開 maven-model-builder-3.6.0.jar 這個壓縮包,里面有兩個目錄
在 org/apache/maven/model/ 目錄下有一個 pom-4.0.0.xml ,這個 pom 就是超級 pom ,例如里面就配置了相關的倉庫信息