一、什么是 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
從哪個下載的呀?都把我搞糊涂了,別急,我花了個流程圖,它的查找順序是這樣的:本地不需要網絡,優先從本地找;找不到,再去速度較高的內網私服找;然后才是速度稍低的外網遠程倉庫找。
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 詳細命令參考:http://www.lxweimin.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
點進去,只有 src
文件夾和 pom.xml
文件:src
是最重要的目錄,代碼和測試用例以及資源都是放在這里的,對于 maven 項目而言,pom.xml
也是必不可少的。
用 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 就引入了 junit
和 cglib
兩個 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.0
,maven
將不會再從倉庫下載新的可用的 1.0
文件。若要下載更新的代碼,maven-test
的版本需要升到 1.1
。
快照是一種特殊的版本,指定了某個當前的開發進度的副本。不同于常規的版本,maven
每次構建都會在遠程倉庫中檢查新的快照。我們自己的模塊依賴了同事開發的模塊,正常來說,同事會每次發布更新代碼的快照到倉庫中。
新建項目的默認版本號就是快照版,比如上面用 maven 命令新建的 maven-test 項目:
4.2 依賴范圍
- scope
maven 項目不同的階段引入到 classpath 中的依賴是不同的,例如,編譯時,maven 會將與編譯相關的依賴引入 classpath 中,測試時,maven 會將測試相關的的依賴引入到 classpath 中,運行時,maven 會將與運行相關的依賴引入 classpath 中,而依賴范圍就是用來控制依賴于這三種 classpath 的關系。 如下圖所示:
scope 表示依賴的范圍,它有 compile(編譯階段)、test(測試階段)、provided(供應階段)、runtime(運行階段)、system(系統階段)、import(導入階段)
六個可選值。其中 compile
是默認的。system
和 import
用得少,不詳細講。
不同依賴的適用范圍不一樣,舉幾個最典型的栗子:
范圍 | 編譯有效 | 測試有效 | 運行時有效 | 打包有效 | 示例 |
---|---|---|---|---|---|
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
項目依賴 JavaMavenService1
,JavaMavenService1
項目依賴 JavaMavenService2
。
pom.xml 文件配置好依賴關系后,必須首先 mvn install 后,依賴的 jar 包才能使用。比如:
-
WebMavenDemo
的pom.xml
文件想能編譯通過,JavaMavenService1
必須mvn install
-
JavaMavenService
的pom.xml
文件想能編譯通過,JavaMavenService2
必須mvn install
傳遞性:
假設我們現在 JavaMavenService2
增加 spring-core
,那就會發現WebMavenDemo
和 JavaMavenService1
也會自動的增加了這個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
最后
如果看到這里,喜歡這篇文章的話,請轉發、點贊。微信搜索「一個優秀的廢人」,歡迎關注。
回復「1024」送你一套完整的 java、python、c++、go、前端、linux、算法、大數據、人工智能、小程序以及英語教程。
回復「電子書」送你 50+ 本 java 電子書。