Maven實(shí)戰(zhàn)與原理分析(二):maven實(shí)戰(zhàn)

學(xué)Maven,這篇萬余字的教程,真的夠用了!

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

1 Maven 介紹

1.1 為什么使用 Maven

由于 Java 的生態(tài)非常豐富,無論你想實(shí)現(xiàn)什么功能,都能找到對(duì)應(yīng)的工具類,這些工具類都是以 jar 包的形式出現(xiàn)的,例如 Spring,SpringMVC、MyBatis、數(shù)據(jù)庫驅(qū)動(dòng),等等,都是以 jar 包的形式出現(xiàn)的,jar 包之間會(huì)有關(guān)聯(lián),在使用一個(gè)依賴之前,還需要確定這個(gè)依賴所依賴的其他依賴,所以,當(dāng)項(xiàng)目比較大的時(shí)候,依賴管理會(huì)變得非常麻煩臃腫,這是 Maven 解決的第一個(gè)問題。

Maven 還可以處理多模塊項(xiàng)目。簡(jiǎn)單的項(xiàng)目,單模塊分包處理即可,如果項(xiàng)目比較復(fù)雜,要做成多模塊項(xiàng)目,例如一個(gè)電商項(xiàng)目有訂單模塊、會(huì)員模塊、商品模塊、支付模塊...,一般來說,多模塊項(xiàng)目,每一個(gè)模塊無法獨(dú)立運(yùn)行,要多個(gè)模塊合在一起,項(xiàng)目才可以運(yùn)行,這個(gè)時(shí)候,借助 Maven 工具,可以實(shí)現(xiàn)項(xiàng)目的一鍵打包。

Maven 之前,我們更多的是使用 Ant 的項(xiàng)目構(gòu)建工具,Ant 有一個(gè)特點(diǎn),每次都得寫,每次都寫的差不多,配置也臃腫。所以,后來搞出來 Maven。Maven 就是最先進(jìn)的版本構(gòu)建工具嗎?不是的,只不過,目前在 Java 領(lǐng)域 Maven 使用比較多。除了 Maven,還有 Gradle。

1.2 Maven 是什么

Maven 是一個(gè)項(xiàng)目管理工具,它包含了一個(gè)項(xiàng)目對(duì)象模型(Project Object Model),反映在配置中,就是一個(gè) pom.xml 文件。是一組標(biāo)準(zhǔn)集合,一個(gè)項(xiàng)目的生命周期、一個(gè)依賴管理系統(tǒng),另外還包括定義在項(xiàng)目生命周期階段的插件(plugin)以及目標(biāo)(goal)。

當(dāng)我們使用 Maven 的使用,通過一個(gè)自定義的項(xiàng)目對(duì)象模型,pom.xml 來詳細(xì)描述我們自己的項(xiàng)目。

Maven 中的有兩大核心:

  • 依賴管理:對(duì) jar 的統(tǒng)一管理(Maven 提供了一個(gè) Maven 的中央倉庫,mvnrepository.com/,當(dāng)我們?cè)陧?xiàng)目中添加完… 會(huì)自動(dòng)去中央倉庫下載相關(guān)的依賴,并且解決依賴的依賴問題)
  • 項(xiàng)目構(gòu)建:對(duì)項(xiàng)目進(jìn)行編譯、測(cè)試、打包、部署、上傳到私服等

2. Maven 安裝

  • Maven 是 Java 項(xiàng)目,因此必須先安裝 JDK。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

下載 Maven:

  • 下載 Maven

下載地址:maven.apache.org/download.cg…

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

  • 解壓并配置

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

配置,只需要配置環(huán)境變量即可:

首先配置 MAVEN_HOME:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

然后配置環(huán)境變量:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

  • 檢驗(yàn)安裝

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

如果使用了 IntelliJ IDEA ,可以不用去額外下載 Maven,直接使用 IDEA 中自帶的 Maven 插件即可。IntelliJ IDEA 中自帶的 Maven 插件在 \ideaIU-2019.2.4.win\plugins\maven\lib\maven3

3. Maven 配置

實(shí)際上,沒有特殊需求的話,安裝好之后直接就可以用了。一般來說,還是需要稍微配置一下,比如中央倉庫的問題。默認(rèn)使用 Maven 自己的中央倉庫,使用起來網(wǎng)速比較慢,這個(gè)時(shí)候,可以通過修改配置文件,將倉庫改成國(guó)內(nèi)的鏡像倉庫,國(guó)內(nèi)倉庫使用較多的是阿里巴巴的倉庫。

3.1 倉庫類型

倉庫類型 說明
本地倉庫 就是你自己電腦上的倉庫,每個(gè)人電腦上都有一個(gè)倉庫,默認(rèn)位置在 當(dāng)前用戶名\.m2\repository
私服倉庫 一般來說是公司內(nèi)部搭建的 Maven 私服,處于局域網(wǎng)中,訪問速度較快,這個(gè)倉庫中存放的 jar 一般就是公司內(nèi)部自己開發(fā)的 jar
中央倉庫 有 Apache 團(tuán)隊(duì)來維護(hù),包含了大部分的 jar,早期不包含 Oracle 數(shù)據(jù)庫驅(qū)動(dòng),從 2019 年 8 月開始,包含了 Oracle 驅(qū)動(dòng)

現(xiàn)在存在 3 個(gè)倉庫,那么 jar 包如何查找呢?

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

3.2 本地倉庫配置

本地倉庫默認(rèn)位置在 當(dāng)前用戶名\.m2\repository,這個(gè)位置可以自定義,但是不建議大家自定義這個(gè)地址,有幾個(gè)原因:

  1. 雖然所有的本地的 jar 都放在這個(gè)倉庫中,但是并不會(huì)占用很大的空間。
  2. 默認(rèn)的位置比較隱蔽,不容易碰到

技術(shù)上來說,當(dāng)然是可以自定義本地倉庫位置的,在 conf/settings.xml 中自定義本地倉庫位置:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

3.3 遠(yuǎn)程鏡像配置

由于默認(rèn)的中央倉庫下載較慢,因此,也可以將遠(yuǎn)程倉庫地址改為阿里巴巴的倉庫地址:

<mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>central</mirrorOf>
        <name>Nexus aliyun</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
復(fù)制代碼

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

這段配置,加在 settings.xml 中的 mirrors 節(jié)點(diǎn)中:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

4. Maven 常用命令

Maven 中有一些常見的命令,如果使用 Eclipse 需要手動(dòng)敲命令,如果使用 IDEA 的話,可以不用命令,直接點(diǎn)點(diǎn)點(diǎn)就可以了。

常用命令 中文含義 說明
mvn clean 清理 這個(gè)命令可以用來清理已經(jīng)編譯好的文件
mvn compile 編譯 將 Java 代碼編譯成 Class 文件
mvn test 測(cè)試 項(xiàng)目測(cè)試
mvn package 打包 根據(jù)用戶的配置,將項(xiàng)目打成 jar 包或者 war 包
mvn install 安裝 手動(dòng)向本地倉庫安裝一個(gè) jar
mvn deploy 上傳 將 jar 上傳到私服

這里需要注意的是,這些命令都不是獨(dú)立運(yùn)行的,它有一個(gè)順序。舉個(gè)簡(jiǎn)單例子:

我想將 jar 上傳到私服,那么就要構(gòu)建 jar,就需要執(zhí)行 package 命令,要打包,當(dāng)然也需要測(cè)試,那就要走 mvn test 命令,要測(cè)試就要先編譯.....,因此,最終所有的命令都會(huì)執(zhí)行一遍。不過,開發(fā)者也可以手動(dòng)配置不執(zhí)行某一個(gè)命令,這就是跳過。一般來是,除了測(cè)試,其他步驟都不建議跳過。

當(dāng)然,如果開發(fā)者使用了 IDEA ,這些命令不用手動(dòng)敲,點(diǎn)一下就行:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

4.1 通過命令來構(gòu)建項(xiàng)目

可以直接通過命令來構(gòu)建一個(gè) Maven 項(xiàng)目,不過在實(shí)際開發(fā)中,一般使用 Eclipse 或者 IDEA 就可以直接創(chuàng)建 Maven 項(xiàng)目了。

創(chuàng)建命令:

mvn archetype:generate -DgroupId=org.javaboy -DartifactId=firstapp -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
復(fù)制代碼

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

看到如下提示,表示項(xiàng)目創(chuàng)建成功:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

項(xiàng)目創(chuàng)建成功后,就兩個(gè)文件:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

說明對(duì)一個(gè)任何一個(gè)項(xiàng)目而言,最最核心的就是這兩個(gè)。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

pom.xml 中,則定義了所有的項(xiàng)目配置。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

4.2 對(duì)項(xiàng)目進(jìn)行打包

接下來,我們通過 mvn package 命令可以將剛剛創(chuàng)建的項(xiàng)目打成一個(gè) jar 包。

在打包之前,需要配置 JDK 的版本至少為 7 以上,因此,我們還需要手動(dòng)修改一下 pom.xml 文件,即添加如下配置:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

添加完成后,執(zhí)行打包命令,注意執(zhí)行所有命令時(shí),命令行要定位到 pom.xml 文件所在的目錄,看到如下提示,表示項(xiàng)目打包成功。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

4.3 將項(xiàng)目安裝到本地倉庫

如果需要將項(xiàng)目安裝到本地倉庫,可以直接執(zhí)行 mvn install 命令,注意,mvn install 命令會(huì)包含上面的 mvn package 過程。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

安裝到本地倉庫之后,這個(gè)時(shí)候,點(diǎn)開自己的本地倉庫,就可以看到相關(guān)的 jar 了。

5. IDEA 中使用 Maven

不同于 Eclipse,IDEA 安裝完成后,就可以直接使用 Maven 了。

5.1 Maven 相關(guān)配置

IDEA 中,Maven 的配置在 File->Settings->Build,Execution,Deployment->Build Tools->Maven:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

5.2 JavaSE 工程創(chuàng)建

首先在創(chuàng)建一個(gè)工程時(shí),選擇 Maven 工程:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

如果勾選上 Create from archetype ,則表示可以根據(jù)一個(gè)項(xiàng)目骨架(項(xiàng)目模板)來創(chuàng)建一個(gè)新的工程,不過,如果只是創(chuàng)建 JavaSE 項(xiàng)目,則不用選擇項(xiàng)目骨架。直接 Next 即可。然后填入項(xiàng)目的坐標(biāo),即 groupId 和 artifactId。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

填完之后,直接 Next 即可。這樣,我們就會(huì)獲取一個(gè) JavaSE 工程,項(xiàng)目結(jié)構(gòu)和你用命令創(chuàng)建出來的項(xiàng)目一模一樣。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

5.3 JavaWeb 工程創(chuàng)建

在 IDEA 中,創(chuàng)建 Maven Web 項(xiàng)目,有兩種思路:

  • 首先創(chuàng)建一個(gè) JavaSE 項(xiàng)目,然后手動(dòng)將 JavaSE 項(xiàng)目改造成一個(gè) JavaWeb 項(xiàng)目
  • 創(chuàng)建項(xiàng)目時(shí)選擇項(xiàng)目骨架,骨架就選擇 webapp

兩種方式中,推薦使用第一種方式。

5.3.1 改造 JavaSE 項(xiàng)目

這種方式,首先創(chuàng)建一個(gè) JavaSE 項(xiàng)目,創(chuàng)建步驟和上面的一致。

項(xiàng)目創(chuàng)建完成后,首先修改 pom.xml ,配置項(xiàng)目的打包格式為 war 包。 這樣,IDEA 就知道當(dāng)前項(xiàng)目是一個(gè) Web 項(xiàng)目:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

然后,選中 JavaSE 工程,右鍵單擊,選擇 Open Module Settings,或者直接按 F4,然后選擇 Web,如下圖:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

接下來,在 webapp 目錄中,添加 web.xml 文件。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

注意,一定要修改 web.xml 文件位置:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

配置完成后,點(diǎn)擊 OK 退出。

項(xiàng)目創(chuàng)建完成后,接下來就是部署了。

部署,首先點(diǎn)擊 IDEA 右上角的 Edit Configurations:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

然后,配置 Tomcat:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

接下來選擇 Deployment 選項(xiàng)卡,配置要發(fā)布的項(xiàng)目:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

最后,點(diǎn)擊 IDEA 右上角的三角符號(hào),啟動(dòng)項(xiàng)目。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

5.3.2 通過 webapp 骨架直接創(chuàng)建

這種方式比較簡(jiǎn)單,基本上不需要額外的配置,項(xiàng)目創(chuàng)建完成后,就是一個(gè) web 項(xiàng)目。只需要我們?cè)趧?chuàng)建項(xiàng)目時(shí),選擇 webapp 骨架即可。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

選擇骨架之后,后面的步驟和前文一致。

項(xiàng)目創(chuàng)建成功后,只有 webapp 目錄,這個(gè)時(shí)候,自己手動(dòng)創(chuàng)建 java 和 resources 目錄,創(chuàng)建完成后,右鍵單擊,選擇 Mark Directory As,將 java 目錄標(biāo)記為 sources root,將 resources 目錄標(biāo)記為 resources root 即可。

凡是在 IDEA 右下角看到了 Enable Auto Import 按鈕,一定點(diǎn)一下

6. Maven 依賴管理

Maven 項(xiàng)目,如果需要使用第三方的控件,都是通過依賴管理來完成的。這里用到的一個(gè)東西就是 pom.xml 文件,概念叫做項(xiàng)目對(duì)象模型(POM,Project Object Model),我們?cè)?pom.xml 中定義了 Maven 項(xiàng)目的形式,所以,pom.xml 相當(dāng)于是 Maven 項(xiàng)目的一個(gè)地圖。就類似于 web.xml 文件用來描述三大 web 組件一樣。

這個(gè)地圖中都涉及到哪些東西呢?

6.1 Maven 坐標(biāo)

<dependencies>
  <dependency>
    <groupId>junit</groupId>
    junit
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
</dependencies>
復(fù)制代碼

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

  • dependencies

在 dependencies 標(biāo)簽中,添加項(xiàng)目需要的 jar 所對(duì)應(yīng)的 maven 坐標(biāo)。

  • dependency

一個(gè) dependency 標(biāo)簽表示一個(gè)坐標(biāo)

  • groupId

團(tuán)體、公司、組織機(jī)構(gòu)等等的唯一標(biāo)識(shí)。團(tuán)體標(biāo)識(shí)的約定是它以創(chuàng)建這個(gè)項(xiàng)目的組織名稱的逆向域名(例如 org.javaboy)開頭。一個(gè) Maven 坐標(biāo)必須要包含 groupId。一些典型的 groupId 如 apache 的 groupId 是 org.apache.

  • artifactId

artifactId 相當(dāng)于在一個(gè)組織中項(xiàng)目的唯一標(biāo)識(shí)符。

  • version

一個(gè)項(xiàng)目的版本。一個(gè)項(xiàng)目的話,可能會(huì)有多個(gè)版本。如果是正在開發(fā)的項(xiàng)目,我們可以給版本號(hào)加上一個(gè) SNAPSHOT,表示這是一個(gè)快照版(新建項(xiàng)目的默認(rèn)版本號(hào)就是快照版)

  • scope

表示依賴范圍。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

我們添加了很多依賴,但是不同依賴的使用范圍是不一樣的。最典型的有兩個(gè),一個(gè)是數(shù)據(jù)庫驅(qū)動(dòng),另一個(gè)是單元測(cè)試。

數(shù)據(jù)庫驅(qū)動(dòng),在使用的過程中,我們自己寫代碼,寫的是 JDBC 代碼,只有在項(xiàng)目運(yùn)行時(shí),才需要執(zhí)行 MySQL 驅(qū)動(dòng)中的代碼。所以,MySQL 驅(qū)動(dòng)這個(gè)依賴在添加到項(xiàng)目中之后,可以設(shè)置它的 scope 為 runtime,編譯的時(shí)候不生效。

單元測(cè)試,只在測(cè)試的時(shí)候生效,所以可以設(shè)置它的 scope 為 test,這樣,當(dāng)項(xiàng)目打包發(fā)布時(shí),單元測(cè)試的依賴就不會(huì)跟著發(fā)布。

6.2 依賴沖突

  • 依賴沖突產(chǎn)生的原因

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

在圖中,a.jar 依賴 b.jar,同時(shí) a.jar 依賴 d.jar,這個(gè)時(shí)候,a 和 b、d 的關(guān)系是直接依賴的關(guān)系,a 和 c 的關(guān)系是間接依賴的關(guān)系。

6.2.1 沖突解決

  1. 先定義先使用
  2. 路徑最近原則(直接聲明使用)

以 spring-context 為例,下圖中 x 表示失效的依賴(優(yōu)先級(jí)低的依賴,即路徑近的依賴優(yōu)先使用):

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

上面這兩條是默認(rèn)行為。

我們也可以手動(dòng)控制。手動(dòng)控制主要是通過排除依賴來實(shí)現(xiàn),如下:

<dependency>
    <groupId>org.springframework</groupId>
    spring-context
    <version>5.1.9.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            spring-core
        </exclusion>
    </exclusions>
</dependency>
復(fù)制代碼

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

這個(gè)表示從 spring-context 中排除 spring-core 依賴。

7. Maven 私服

Maven 倉庫管理也叫 Maven 私服或者代理倉庫。使用 Maven 私服有兩個(gè)目的:

  1. 私服是一個(gè)介于開發(fā)者和遠(yuǎn)程倉庫之間的代理
  2. 私服可以用來部署公司自己的 jar

7.1 Nexus 介紹

Nexus 是一個(gè)強(qiáng)大的 Maven 倉庫管理工具,使用 Nexus 可以方便的管理內(nèi)部倉庫同時(shí)簡(jiǎn)化外部倉庫的訪問。官網(wǎng)是:www.sonatype.com/

7.2 安裝

  • 下載

下載地址:www.sonatype.com/download-os…

  • 解壓

將下載下來的壓縮包,拷貝到一個(gè)沒有中文的路徑下,然后解壓。

  • 啟動(dòng)

解壓之后,打開 cmd 窗口(以管理員身份打開 cmd 窗口),然后定位了 nexus 解壓目錄,執(zhí)行 nexus.exe/run 命令啟動(dòng)服務(wù)。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

這個(gè)啟動(dòng)稍微有點(diǎn)慢,大概有 1 兩分鐘的樣子

啟動(dòng)成功后,瀏覽器輸入 http://lcoalhost:8081 打開管理頁面。

打開管理頁面后,點(diǎn)擊右上角上的登錄按鈕進(jìn)行登錄,默認(rèn)的用戶名/密碼是 admin/admin123。當(dāng)然,用戶也可以點(diǎn)擊設(shè)置按鈕,手動(dòng)配置其他用戶。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

點(diǎn)擊 Repositories 可以查看倉庫詳細(xì)信息:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

7.2.1 倉庫類型

名稱 說明
proxy 表示這個(gè)倉庫是一個(gè)遠(yuǎn)程倉庫的代理,最典型的就是代理 Maven 中央倉庫
hosted 宿主倉庫,公司自己開發(fā)的一些 jar 存放在宿主倉庫中,以及一些在 Maven 中央倉庫上沒有的 jar
group 倉庫組,包含代理倉庫和宿主倉庫
virtual 虛擬倉庫

7.2.2 上傳 jar

上傳 jar,配置兩個(gè)地方:

  • Maven 的 conf/settings.xml 文件配置:
<server>
  <id>releases</id>
  <username>admin</username>
  <password>admin123</password>
</server>
<server>
  <id>snapshots</id>
  <username>admin</username>
  <password>admin123</password>
</server>
復(fù)制代碼

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

在要上傳 jar 的項(xiàng)目的 pom.xml 文件中,配置上傳路徑:

<distributionManagement>
    <repository>
        <id>releases</id>
        <url>http://localhost:8081/repository/maven-releases/</url>
    </repository>
    <snapshotRepository>
        <id>snapshots</id>
        <url>http://localhost:8081/repository/maven-snapshots/</url>
    </snapshotRepository>
</distributionManagement>
復(fù)制代碼

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

配置完成后,點(diǎn)擊 deploy 按鈕,或者執(zhí)行 mvn deploy 命令就可以將 jar 上傳到私服上。

7.2.3 下載私服上的 jar

直接在項(xiàng)目中添加依賴,添加完成后,額外增加私服地址即可:

<repositories>
    <repository>
        <id>local-repository</id>
        <url>http://localhost:8081/repository/maven-public/</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>
復(fù)制代碼

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

8. 聚合工程

所謂的聚合工程,實(shí)際上也就是多模塊項(xiàng)目。在一個(gè)比較大的互聯(lián)網(wǎng)項(xiàng)目中,項(xiàng)目需要拆分成多個(gè)模塊進(jìn)行開發(fā),比如訂單模塊、VIP 模塊、支付模塊、內(nèi)容管理模塊、CMS、CRM 等等。這種拆分方式,實(shí)際上更接近于微服務(wù)的思想。在一個(gè)模塊中,還可以繼續(xù)進(jìn)行拆分,例如分成 dao、service、controller 等。

有人可能會(huì)說,這個(gè)分包不就行了嗎?

小項(xiàng)目當(dāng)然可以分包,大項(xiàng)目就沒法分包了。比如,在一個(gè)大的電商系統(tǒng)中,有一個(gè)子模塊叫做用戶管理、還有一個(gè)子模塊叫做訂單管理,這兩個(gè)子模塊都涉及到用戶,像這種情況,我們就需要將用戶類單獨(dú)提取出來,做成單獨(dú)的模塊,供其他模塊調(diào)用。

8.1 多模塊項(xiàng)目展示

|--javaboy-parent
      |-- javaboy-cms
      |-- javaboy-crm
      |-- javaboy-manger
           |-- javaboy-manager-model
           |-- javaboy-manager-dao
           |-- javaboy-manager-service
           |-- javaboy-manager-web
復(fù)制代碼

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

以 javaboy-manger 為例,javaboy-manager 本身并不提供功能,它只負(fù)責(zé)管理他自己的子模塊,而他的子模塊每一個(gè)都無法獨(dú)立運(yùn)行,需要四個(gè)結(jié)合在一起,才可以運(yùn)行。項(xiàng)目打包時(shí),model、dao、service 都將打包成 jar,然后會(huì)自動(dòng)將打包好的 jar 復(fù)制到 web 中,再自動(dòng)將 web 打包成 war 包。

8.2 IDEA 中創(chuàng)建聚合工程

1.創(chuàng)建一個(gè)空的 Maven 項(xiàng)目:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

項(xiàng)目創(chuàng)建完成后,由于 parent 并不參與業(yè)務(wù)的實(shí)現(xiàn),只是用來管理它的子模塊,因此,src 目錄可以將其刪除。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

2.選中當(dāng)前工程,右鍵單擊,New->Module

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

然后繼續(xù)選擇創(chuàng)建一個(gè) Maven 項(xiàng)目:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

在 IDEA 中,已經(jīng)默認(rèn)指明了當(dāng)前 Module 的 parent,開發(fā)者只需要填入當(dāng)前 Module 的 artifactId 即可:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

javaboy-manager 創(chuàng)建完成后,此時(shí),觀察 javaboy-parent 的 pom.xml 文件,發(fā)現(xiàn)它自動(dòng)加上了 packing 屬性:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

其中,它的 packaging 屬性值為 pom,這表示它是一個(gè)聚合工程,同時(shí),他還多了 modules 節(jié)點(diǎn),指明了它自己的子模塊。 同時(shí),注意 javaboy-manager ,它自身多了一個(gè) parent 節(jié)點(diǎn),這個(gè) parent 節(jié)點(diǎn)描述了它的父模塊的屬性值:

<parent>
    javaboy-parent
    <groupId>org.javaboy</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>
復(fù)制代碼

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

這個(gè) parent 不僅僅是一個(gè)簡(jiǎn)單的父子關(guān)系描述,它存在繼承關(guān)系,一般我們可以在 parent 中統(tǒng)一定義依賴或者插件的版本號(hào)

3.由于 javaboy-manager 本身也是一個(gè)聚合工程,因此,javaboy-manager 的 src 目錄也可以刪除。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

4.選中 javaboy-manager,右鍵單擊,New->Module 創(chuàng)建一個(gè)新的 Maven 模塊出來。這個(gè)步驟類似于第二步,不在贅述。 這里,新的 javaboy-manager-model 創(chuàng)建成功后,我們手動(dòng)配置它的 packaging 屬性值為 jar。

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

5.依照第 4 步,再分別創(chuàng)建 javaboy-manager-service 以及 javaboy-manager-dao 6.繼續(xù)創(chuàng)建 javaboy-manager-web 模塊,不同于其他模塊,web 模塊需要打包成 war。web 模塊創(chuàng)建可以參考【第五篇文章】。 7.web 工程創(chuàng)建完成后,完善模塊之間的繼承關(guān)系。

javaboy-manager-web 依賴 javaboy-manager-service javaboy-manager-service 依賴 javaboy-manager-dao javaboy-manager-dao 依賴 javaboy-manager-model

注意,依賴默認(rèn)是有傳遞性的,即在 javaboy-manager-dao 中依賴了 javaboy-manager-model,在 javaboy-manager-service 也能訪問到。

配置后的依賴關(guān)系如下圖:

![](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== "點(diǎn)擊并拖拽以移動(dòng)")

接下來就可以在不同的模塊中寫代碼,然后進(jìn)行項(xiàng)目部署了。部署方式參考【第五篇文章】

有一個(gè)需要注意的地方,在多模塊項(xiàng)目中,web 項(xiàng)目打包需要注意以下問題:

  1. 不可以直接單獨(dú)打包
  2. 如果要打包,有兩種方式:
  • 第一種就是先手動(dòng)挨個(gè)將 model、dao、service 安裝到本地倉庫
  • 從聚合工程處打包,即從 web 的parent 處打包。

微信公眾號(hào)【程序員黃小斜】作者是前螞蟻金服Java工程師,專注分享Java技術(shù)干貨和求職成長(zhǎng)心得,不限于BAT面試,算法、計(jì)算機(jī)基礎(chǔ)、數(shù)據(jù)庫、分布式、spring全家桶、微服務(wù)、高并發(fā)、JVM、Docker容器,ELK、大數(shù)據(jù)等。關(guān)注后回復(fù)【book】領(lǐng)取精選20本Java面試必備精品電子書。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容