Maven實(shí)戰(zhàn)與原理分析(一):maven超全使用指南總結(jié)

頭條一面竟然問(wèn)我Maven育苟?

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

maven package和maven install 有什么區(qū)別靴姿?

你常用的maven命令有哪些?

<dependencyManagement> 是干什么的?

還有用過(guò)其它構(gòu)建工具嗎? 和maven有啥區(qū)別肛宋?

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

這幾個(gè)問(wèn)題都可以脫口而出咐容,你應(yīng)該是有點(diǎn) maven 能耐授药,寫(xiě)代碼去吧幅疼,不用看了

點(diǎn)贊+收藏 就學(xué)會(huì)系列,文章收錄在 GitHub JavaEgg 堂飞,N線互聯(lián)網(wǎng)開(kāi)發(fā)必備技能兵器譜

1.Maven是啥:

Maven是Apache軟件基金會(huì)唯一維護(hù)的一款自動(dòng)化構(gòu)建工具灌旧,專注于服務(wù)Java平臺(tái)的項(xiàng)目構(gòu)建依賴管理

Maven是基于項(xiàng)目對(duì)象模型(POM)绰筛,可以通過(guò)一小段描述信息來(lái)管理項(xiàng)目的構(gòu)建枢泰、報(bào)告和文檔的軟件項(xiàng)目管理工具。

2.Maven可以干啥:

  • 添加第三方j(luò)ar包
  • jar包之間的依賴關(guān)系: Maven 可以替我們自動(dòng)的將當(dāng)前 jar 包所依賴的其他所有 jar 包全部導(dǎo)入進(jìn)來(lái)
  • 獲取第三方j(luò)ar包: Maven 提供了一個(gè)完全統(tǒng)一規(guī)范的 jar 包管理體系铝噩,只需要在項(xiàng)目中以坐標(biāo)的方式依賴一個(gè) jar 包衡蚂,Maven 就會(huì)自動(dòng)從中央倉(cāng)庫(kù)進(jìn)行下載到本地倉(cāng)庫(kù)
  • 將項(xiàng)目拆分成多個(gè)工程模塊
  • 構(gòu)建項(xiàng)目(打包,編譯等)

3.構(gòu)建項(xiàng)目的幾個(gè)主要環(huán)節(jié):

  • 清理(clean):刪除以前的編譯結(jié)果骏庸,為重新編譯做好準(zhǔn)備
  • 編譯(compile):將Java 源程序編譯為字節(jié)碼文件
  • 測(cè)試(test):針對(duì)項(xiàng)目中的關(guān)鍵點(diǎn)進(jìn)行測(cè)試毛甲,確保項(xiàng)目在迭代開(kāi)發(fā)過(guò)程中關(guān)鍵點(diǎn)的正確性
  • 報(bào)告:在每一次測(cè)試后以標(biāo)準(zhǔn)的格式記錄和展示測(cè)試結(jié)果
  • 打包(package):將一個(gè)包含諸多文件的工程封裝為一個(gè)壓縮文件用于安裝或部署。Java 工程對(duì)應(yīng) jar 包具被,Web工程對(duì)應(yīng) war 包玻募。
  • 安裝(install):在 Maven 環(huán)境下特指將打包的結(jié)果——jar 包或 war 包安裝到本地倉(cāng)庫(kù)中。
  • 部署(deploy):將打包的結(jié)果部署到遠(yuǎn)程倉(cāng)庫(kù)或?qū)?war 包部署到服務(wù)器上運(yùn)行一姿。

4.Maven常用命令

  • mvn -version/-v —— 顯示版本信息
  • mvn clean —— 清空生成的文件
  • mvn compile —— 編譯
  • mvn test —— 編譯并測(cè)試
  • mvn package —— 生成target目錄七咧,編譯跃惫、測(cè)試代碼,生成測(cè)試報(bào)告艾栋,生成jar/war文件
  • mvn site —— 生成項(xiàng)目相關(guān)信息的網(wǎng)站
  • mvn clean compile —— 表示先運(yùn)行清理之后運(yùn)行編譯爆存,會(huì)將代碼編譯到target文件夾中
  • mvn clean package —— 運(yùn)行清理和打包
  • mvn clean install —— 運(yùn)行清理和安裝,會(huì)將打好的包安裝到本地倉(cāng)庫(kù)中裹粤,以便其他的項(xiàng)目可以調(diào)用
  • mvn clean deploy —— 運(yùn)行清理和發(fā)布

5.Maven核心概念

Maven 能夠?qū)崿F(xiàn)自動(dòng)化構(gòu)建是和它的內(nèi)部原理分不開(kāi)的终蒂,這里我們從 Maven 的九個(gè)核心概念入手蜂林, 看看 Maven 是如何實(shí)現(xiàn)自動(dòng)化構(gòu)建的

  • POM
  • 約定的目錄結(jié)構(gòu)
  • 坐標(biāo)
  • 依賴管理
  • 倉(cāng)庫(kù)管理
  • 生命周期
  • 插件和目標(biāo)
  • 繼承
  • 聚合

Maven 的核心程序中僅僅定義了抽象的生命周期遥诉,而具體的操作則是由 Maven 的插件來(lái)完成的≡胄穑可是 Maven 的插件并不包含在 Maven 的核心程序中矮锈,在首次使用時(shí)需要聯(lián)網(wǎng)下載。 下載得到的插件會(huì)被保存到本地倉(cāng)庫(kù)中睁蕾。本地倉(cāng)庫(kù)默認(rèn)的位置是:~.m2\repository苞笨。

5.1. Maven約定的工程目錄:

maven-project.png

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

Java開(kāi)發(fā)領(lǐng)域普遍認(rèn)同的一個(gè)觀點(diǎn):約定>配置>編碼(能用配置解決的問(wèn)題就不編碼,能基于約定的就不配置)

5.2. POM

Project Object Model:項(xiàng)目對(duì)象模型子眶。將 Java 工程的相關(guān)信息封裝為對(duì)象作為便于操作和管理的模型瀑凝。

Maven 工程的核心配置。

5.3. 坐標(biāo)

  • Maven 的坐標(biāo) 使用如下三個(gè)向量在 Maven 的倉(cāng)庫(kù)中唯一的確定一個(gè) Maven 工程臭杰。
    • groupid:公司或組織的域名倒序+當(dāng)前項(xiàng)目名稱
    • artifactId:當(dāng)前項(xiàng)目的模塊名稱
    • version:當(dāng)前模塊的版本
  <groupId>net.lazyegg.maven</groupId>
  Hello
  <version>0.0.1-SNAPSHOT</version>
復(fù)制代碼

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

  • 如何通過(guò)坐標(biāo)到倉(cāng)庫(kù)中查找 jar 包粤咪?

    • 將 gav 三個(gè)向量連起來(lái)
```
net.lazyegg.maven+Hello+0.0.1-SNAPSHOT
復(fù)制代碼
```

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

*   以連起來(lái)的字符串作為目錄結(jié)構(gòu)到倉(cāng)庫(kù)中查找

    net/lazyegg/maven/Hello/0.0.1-SNAPSHOT/Hello-0.0.1-SNAPSHOT.jar

※ 注意:我們自己的 Maven 工程必須執(zhí)行安裝操作才會(huì)進(jìn)入倉(cāng)庫(kù)。安裝的命令是:mvn install

5.4. 依賴

Maven 中最關(guān)鍵的部分渴杆,我們使用 Maven 最主要的就是使用它的依賴管理功能寥枝。要理解和掌握 Maven 的依賴管理,我們只需要解決以下幾個(gè)問(wèn)題:

① 依賴的目的是什么

當(dāng) A jar 包用到了 B jar 包中的某些類時(shí)磁奖,A 就對(duì) B 產(chǎn)生了依賴囊拜,這是概念上的描述。那么如何在項(xiàng)目中以依賴的方式引入一個(gè)我們需要的 jar 包呢比搭? 答案非常簡(jiǎn)單冠跷,就是使用 dependency 標(biāo)簽指定被依賴 jar 包的坐標(biāo)就可以了。

<dependency>
    <groupId>net.lazyegg.maven</groupId>
    Hello
    <version>0.0.1-SNAPSHOT</version>
    <scope>compile</scope>            
</dependency>
復(fù)制代碼

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

② 依賴的范圍

有時(shí)依賴信息中除了目標(biāo) jar 包的坐標(biāo)還有一個(gè) scope 設(shè)置身诺,這就是依賴的范圍蜜托。依賴的范圍有幾個(gè)可選值,常用的有:compile戚长、test盗冷、provided 三個(gè),當(dāng)然還有不常用的 runtime同廉、system..

  • compile默認(rèn)范圍仪糖,編譯測(cè)試運(yùn)行都有效

  • provided:在編譯和測(cè)試時(shí)有效

  • runtime:在測(cè)試和運(yùn)行時(shí)有效

  • test:只在測(cè)試時(shí)有效

  • system:在編譯和測(cè)試時(shí)有效柑司,與本機(jī)系統(tǒng)關(guān)聯(lián),可移植性差

  • 常用依賴范圍有效性總結(jié)

compile test provided
主程序 ×
測(cè)試程序
參與部署 × ×

③ 依賴的傳遞性

A 依賴 B锅劝,B 依賴 C攒驰,A 能否使用 C 呢?那要看 B 依賴 C 的范圍是不是 compile故爵,如果是則可用玻粪,否則不可用。

④ 依賴的排除

如果我們?cè)诋?dāng)前工程中引入了一個(gè)依賴是 A诬垂,而 A 又依賴了 B劲室,那么 Maven 會(huì)自動(dòng)將 A 依賴的 B 引入當(dāng) 前工程,但是個(gè)別情況下 B 有可能是一個(gè)不穩(wěn)定版结窘,或?qū)Ξ?dāng)前工程有不良影響很洋。這時(shí)我們可以在引入 A 的時(shí)候?qū)?B 排除。

<dependency>
    <groupId>net.lazyegg.maven</groupId>
    Hello
    <version>0.0.1-SNAPSHOT</version>
    <scope>compile</scope>
    <exclusions>
    <exclusion>
    <groupId>commons-logging</groupId>
    commons-logging
    </exclusion>
    </exclusions>
</dependency>
復(fù)制代碼

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

⑤ 統(tǒng)一管理所依賴 jar 包的版本隧枫,對(duì)同一個(gè)框架的一組 jar 包最好使用相同的版本喉磁。為了方便升級(jí)框架,可以將 jar 包的版本信息統(tǒng)一提取出來(lái)

  • 統(tǒng)一聲明版本號(hào)
<properties>
    <starfish.spring.version>4.1.1.RELEASE</starfish.spring.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
復(fù)制代碼

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

  • 引用前面聲明的版本號(hào)
<dependency>
    <groupId>org.springframework</groupId>
    spring-core
    <version>${starfish.spring.version}</version>
    <scope>compile</scope>
</dependency>
復(fù)制代碼

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

⑥ 依賴的原則:解決 jar 包沖突

  • 路徑最短者優(yōu)先
  • 路徑相同時(shí)先聲明者優(yōu)先

項(xiàng)目版本沖突時(shí)候的那種蛋疼的感覺(jué)官脓,只有疼過(guò)的才知道协怒,所以,我們來(lái)看看疼過(guò)的人是怎么解決的卑笨,推薦一個(gè)IDEA插件孕暇,Maven Helper,比自帶的好用湾趾,一目了然

maven-helper.png

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

5.5. 倉(cāng)庫(kù)

  • 分類
    • 本地倉(cāng)庫(kù):為當(dāng)前本機(jī)電腦上的所有 Maven 工程服務(wù)
    • 遠(yuǎn)程倉(cāng)庫(kù)
      • 私服:架設(shè)在當(dāng)前局域網(wǎng)環(huán)境下芭商,為當(dāng)前局域網(wǎng)范圍內(nèi)的所有 Maven 工程服務(wù)
      • 中央倉(cāng)庫(kù):架設(shè)在 Internet 上,為全世界所有 Maven 工程服務(wù)
      • 中央倉(cāng)庫(kù)的鏡像:架設(shè)在各個(gè)大洲搀缠,為中央倉(cāng)庫(kù)分擔(dān)流量铛楣。減輕中央倉(cāng)庫(kù)的壓力,同時(shí)更快的響應(yīng)用戶請(qǐng)求艺普,比如阿里的鏡像
  • 倉(cāng)庫(kù)中的文件
    • Maven 的插件
    • 我們自己開(kāi)發(fā)的項(xiàng)目的模塊
    • 第三方框架或工具的 jar 包 ※ 不管是什么樣的 jar 包簸州,在倉(cāng)庫(kù)中都是按照坐標(biāo)生成目錄結(jié)構(gòu),所以可以通過(guò)統(tǒng)一的方式查詢或依賴歧譬,查詢地址:mvnrepository.com/

5.6. 生命周期

5.6.1. 什么是 Maven 的生命周期岸浑?

Maven 生命周期定義了各個(gè)構(gòu)建環(huán)節(jié)的執(zhí)行順序,有了這個(gè)清單瑰步,Maven 就可以自動(dòng)化的執(zhí)行構(gòu)建命令了矢洲。

Maven 有三套相互獨(dú)立的生命周期,分別是:

  • Clean Lifecycle 在進(jìn)行真正的構(gòu)建之前進(jìn)行一些清理工作
  • Default Lifecycle 構(gòu)建的核心部分缩焦,編譯读虏,測(cè)試责静,打包,安裝盖桥,部署等等
  • Site Lifecycle 生成項(xiàng)目報(bào)告灾螃,站點(diǎn),發(fā)布站點(diǎn)

它們是相互獨(dú)立的揩徊,你可以僅僅調(diào)用 clean 來(lái)清理工作目錄腰鬼,僅僅調(diào)用 site 來(lái)生成站點(diǎn)。當(dāng)然你也可以直接運(yùn)行 mvn clean install site 運(yùn)行所有這三套生命周期塑荒。 每套生命周期都由一組階段(Phase)組成熄赡,我們平時(shí)在命令行輸入的命令總會(huì)對(duì)應(yīng)于一個(gè)特定的階段。比 如袜炕,運(yùn)行 mvn clean本谜,這個(gè) clean 是 Clean 生命周期的一個(gè)階段。有 Clean 生命周期偎窘,也有 clean 階段。

5.6.2. Clean 生命周期

Clean 生命周期一共包含了三個(gè)階段:

  • pre-clean 執(zhí)行一些需要在 clean 之前完成的工作
  • clean 移除所有上一次構(gòu)建生成的文件
  • post-clean 執(zhí)行一些需要在 clean 之后立刻完成的工作

5.6.3. Site 生命周期

  • pre-site 執(zhí)行一些需要在生成站點(diǎn)文檔之前完成的工作
  • site 生成項(xiàng)目的站點(diǎn)文檔
  • post-site 執(zhí)行一些需要在生成站點(diǎn)文檔之后完成的工作溜在,并且為部署做準(zhǔn)備
  • site-deploy 將生成的站點(diǎn)文檔部署到特定的服務(wù)器上 這里經(jīng)常用到的是 site 階段和 site-deploy 階段陌知,用以生成和發(fā)布 Maven 站點(diǎn),這可是 Maven 相當(dāng)強(qiáng)大 的功能掖肋,Manager 比較喜歡仆葡,文檔及統(tǒng)計(jì)數(shù)據(jù)自動(dòng)生成,很好看志笼。

5.6.4. Default 生命周期

Default 生命周期是 Maven 生命周期中最重要的一個(gè)沿盅,絕大部分工作都發(fā)生在這個(gè)生命周期中(列出一些重要階段)

  • validate:驗(yàn)證工程是否正確,所有需要的資源是否可用纫溃。
  • compile:編譯項(xiàng)目的源代碼腰涧。
  • test:使用合適的單元測(cè)試框架來(lái)測(cè)試已編譯的源代碼。這些測(cè)試不需要已打包和布署紊浩。
  • package:把已編譯的代碼打包成可發(fā)布的格式窖铡,比如 jar、war 等坊谁。
  • integration-test:如有需要费彼,將包處理和發(fā)布到一個(gè)能夠進(jìn)行集成測(cè)試的環(huán)境。
  • verify:運(yùn)行所有檢查口芍,驗(yàn)證包是否有效且達(dá)到質(zhì)量標(biāo)準(zhǔn)箍铲。
  • install:把包安裝到maven本地倉(cāng)庫(kù),可以被其他工程作為依賴來(lái)使用鬓椭。
  • deploy:在集成或者發(fā)布環(huán)境下執(zhí)行颠猴,將最終版本的包拷貝到遠(yuǎn)程的repository聋庵,使得其他的開(kāi)發(fā)者或者工程可以共享

5.6.5. 生命周期與自動(dòng)化構(gòu)建

運(yùn)行任何一個(gè)階段的時(shí)候,它前面的所有階段都會(huì)被運(yùn)行芙粱,例如我們運(yùn)行 mvn install 的時(shí)候祭玉,代碼會(huì)被編譯,測(cè)試春畔,打包脱货。這就是 Maven 為什么能夠自動(dòng)執(zhí)行構(gòu)建過(guò)程的各個(gè)環(huán)節(jié)的原因。此外律姨,Maven 的插件機(jī)制是完全依賴 Maven 的生命周期的振峻,因此理解生命周期至關(guān)重要。

5.7. 插件和目標(biāo)

  • Maven 的核心僅僅定義了抽象的生命周期择份,具體的任務(wù)都是交由插件完成的
  • 每個(gè)插件都能實(shí)現(xiàn)多個(gè)功能扣孟,每個(gè)功能就是一個(gè)插件目標(biāo)
  • Maven 的生命周期與插件目標(biāo)相互綁定,以完成某個(gè)具體的構(gòu)建任務(wù) 例如:compile 就是插件 maven-compiler-plugin 的一個(gè)目標(biāo)荣赶;pre-clean 是插件 maven-clean-plugin 的一個(gè)目標(biāo)

5.8. 繼承

  • 為什么需要繼承機(jī)制凤价? 由于非 compile 范圍的依賴信息是不能在“依賴鏈”中傳遞的,所以有需要的工程只能單獨(dú)配置
  • 創(chuàng)建父工程 創(chuàng)建父工程和創(chuàng)建一般的 Java 工程操作一致拔创,唯一需要注意的是:打包方式處要設(shè)置為 pom
  • 在子工程中引用父工程 利诺,從當(dāng)前目錄到父項(xiàng)目的 pom.xml 文件的相對(duì)路徑
 <parent>
    <groupId>com.starfish.maven</groupId>
    Parent
    <version>0.0.1-SNAPSHOT</version>
    <!-- 以當(dāng)前文件為基準(zhǔn)的父工程pom.xml文件的相對(duì)路徑 -->
    <relativePath>../Parent/pom.xml</relativePath>
</parent>
復(fù)制代碼

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

此時(shí)如果子工程的 groupId 和 version 如果和父工程重復(fù)則可以刪除。

  • 在父工程中管理依賴 將 Parent 項(xiàng)目中的 dependencies 標(biāo)簽剩燥,用 dependencyManagement 標(biāo)簽括起來(lái)
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            junit
            <version>4.9</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</dependencyManagement> 
復(fù)制代碼

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

在子項(xiàng)目中重新指定需要的依賴慢逾,刪除范圍和版本號(hào)

<dependency>
    <groupId>junit</groupId>
    junit
</dependency>
復(fù)制代碼

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

5.9. 聚合

  • 為什么要使用聚合?

將多個(gè)工程拆分為模塊后灭红,需要手動(dòng)逐個(gè)安裝到倉(cāng)庫(kù)后依賴才能夠生效侣滩。修改源碼后也需要逐個(gè)手動(dòng)進(jìn) 行 clean 操作。而使用了聚合之后就可以批量進(jìn)行 Maven 工程的安裝变擒、清理工作君珠。

如何配置聚合? 在總的聚合工程中使用 modules/module 標(biāo)簽組合赁项,指定模塊工程的相對(duì)路徑即可

原本地址:Maven入門葛躏,讀完這篇就夠了

博客地址:tengj.top/

前言

夜空中最亮的星,2018請(qǐng)照亮我前行~ Maven是我們?nèi)粘i_(kāi)發(fā)都會(huì)用到的悠菜,新年第一天舰攒,把看過(guò)的Maven基礎(chǔ)概念做了整理,作為入門和查閱使用悔醋。

正文

Maven概念

Maven作為一個(gè)構(gòu)建工具摩窃,不僅能幫我們自動(dòng)化構(gòu)建,還能夠抽象構(gòu)建過(guò)程,提供構(gòu)建任務(wù)實(shí)現(xiàn);它跨平臺(tái)猾愿,對(duì)外提供了一致的操作接口鹦聪,這一切足以使它成為優(yōu)秀的、流行的構(gòu)建工具蒂秘。

Maven不僅是構(gòu)建工具泽本,還是一個(gè)依賴管理工具和項(xiàng)目管理工具,它提供了中央倉(cāng)庫(kù)姻僧,能幫我自動(dòng)下載構(gòu)件规丽。

maven的安裝

一:因?yàn)楸救耸莣indow系統(tǒng),所以這里只介紹window下如何安裝撇贺,在安裝Maven之前赌莺,先確認(rèn)已經(jīng)安裝了JDK.

image.png

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

二:接著去Maven官網(wǎng)下載界面下載想要的版本解壓到你想要的目錄就行

image.png

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

image.png

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

三:最后設(shè)置一下環(huán)境變量,將Maven安裝配置到操作系統(tǒng)環(huán)境中松嘶,主要就是配置M2_HOME PATH兩項(xiàng)艘狭,如圖

image.png

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

都搞定后,驗(yàn)證一下翠订,打開(kāi)doc輸入 mvn -v如何得到下面信息就說(shuō)明配置成功了

image.png

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

maven目錄

image.png

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

  • bin目錄

該目錄包含了mvn運(yùn)行的腳本巢音,這些腳本用來(lái)配置java命令,準(zhǔn)備好classpath和相關(guān)的Java系統(tǒng)屬性蕴轨,然后執(zhí)行Java命令港谊。

  • boot目錄:

該目錄只包含一個(gè)文件,該文件為plexus-classworlds-2.5.2.jar橙弱。plexus-classworlds是一個(gè)類加載器框架被去,相對(duì)于默認(rèn)的java類加載器葫督,它提供了更加豐富的語(yǔ)法以方便配置,Maven使用該框架加載自己的類庫(kù)冰啃。

  • conf目錄:

該目錄包含了一個(gè)非常重要的文件settings.xml龙致。直接修改該文件蛀缝,就能在機(jī)器上全局地定制Maven的行為,一般情況下目代,我們更偏向于復(fù)制該文件至/.m2/目錄下(表示用戶目錄)屈梁,然后修改該文件,在用戶范圍定制Maven的行為榛了。

  • lib目錄:

該目錄包含了所有Maven運(yùn)行時(shí)需要的Java類庫(kù)在讶,Maven本身是分模塊開(kāi)發(fā)的,因此用戶能看到諸如maven-core-3.0.jar霜大、maven-model-3.0.jar之類的文件构哺,此外這里還包含一些Maven用到的第三方依賴如commons-cli-1.2.jar、commons-lang-2.6.jar等等。

Maven常用命令說(shuō)明

  • mvn clean:表示運(yùn)行清理操作(會(huì)默認(rèn)把target文件夾中的數(shù)據(jù)清理)曙强。
  • mvn clean compile:表示先運(yùn)行清理之后運(yùn)行編譯残拐,會(huì)將代碼編譯到target文件夾中。
  • mvn clean test:運(yùn)行清理和測(cè)試碟嘴。
  • mvn clean package:運(yùn)行清理和打包溪食。
  • mvn clean install:運(yùn)行清理和安裝,會(huì)將打好的包安裝到本地倉(cāng)庫(kù)中娜扇,以便其他的項(xiàng)目可以調(diào)用错沃。
  • mvn clean deploy:運(yùn)行清理和發(fā)布(發(fā)布到私服上面)。

上面的命令大部分都是連寫(xiě)的袱衷,大家也可以拆分分別執(zhí)行捎废,這是活的,看個(gè)人喜好以及使用需求致燥,Eclipse Run as對(duì)maven項(xiàng)目會(huì)提供常用的命令登疗。

設(shè)置http代理

編輯seeting.xml文件 有時(shí)候你所在的公司基于安全因素考慮,要求你使用通過(guò)安全認(rèn)證的代理訪問(wèn)因特網(wǎng)嫌蚤。這種情況下辐益,就需要為Maven配置HTTP代理,才能讓它正常訪問(wèn)外部倉(cāng)庫(kù)脱吱,以下載所需要的資源智政。首先確認(rèn)自己無(wú)法直接訪問(wèn)公共的maven中央倉(cāng)庫(kù),直接運(yùn)行命令ping repo1.maven.org可以檢查網(wǎng)絡(luò)箱蝠。如果真的需要代理续捂,先檢查一下代理服務(wù)器是否暢通。比如現(xiàn)在有一個(gè)IP地址為218.14.227.197宦搬,端口為3128的代理服務(wù)牙瓢,我們可以運(yùn)行telnet 218.14.227.197 3128來(lái)檢測(cè)該地址的該端口是否暢通。如果得到出錯(cuò)信息间校,需要先獲取正確的代理服務(wù)信息矾克,如果telnet連接正確,則輸入ctrl+]憔足,然后q胁附,回車,退出即可滓彰。

檢查完畢之后控妻,編輯~/.m2/settings.xml文件(如果沒(méi)有該文件,則復(fù)制$M2_HOME/conf/settings.xml)找蜜。添加代理配置如下:

<settings>  
  ...  
  <proxies>  
    <proxy>  
      <id>my-proxy</id>  
      true  
      <protocol>http</protocol>  
      <host>218.14.227.197</host>  
      <port>3128</port>  
      <!--  
        <username>***</username>  
        <password>***</password>  
        <nonProxyHosts>  
          repository.mycom.com|*.google.com  
        </nonProxyHosts>  
      -->  
    </proxy>  
  </proxies>  
  ...  
</settings> 
復(fù)制代碼

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

這段配置十分簡(jiǎn)單饼暑,proxies下可以有多個(gè)proxy元素,如果聲明了多個(gè)proxy元素,則默認(rèn)情況下第一個(gè)被激活的proxy會(huì)生效弓叛。這里聲明了一個(gè)id為my-proxy的代理彰居,active的值為true表示激活該代理,protocol表示使用的代理協(xié)議撰筷,這里是http陈惰。當(dāng)然,最重要的是指定正確的主機(jī)名(host元素)和端口(port元素)毕籽。上述xml配置中注釋掉了username,password,nonProxyHosts幾個(gè)元素抬闯。當(dāng)代理服務(wù)需要認(rèn)證時(shí),就需要配置username和password关筒。nonProxyHost元素用來(lái)指定哪些主機(jī)不需要代理溶握,可以使用"|"符號(hào)來(lái)分隔多個(gè)主機(jī)名。此外蒸播,該配置也支持通配符睡榆,如:*.google.com表示所有以google.com結(jié)尾的域名訪問(wèn)都不要通過(guò)代理。

Maven插件安裝袍榆,基于IDEA

博主現(xiàn)在使用IDEA來(lái)開(kāi)發(fā)的胀屿,所以這里介紹一下IDEA中如何配置引入我們上面下載好的Maven

image.png

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

Maven使用

<?xml version="1.0" encoding="UTF-8"?>
<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.tengj</groupId>
    springBootDemo1
    <version>0.0.1-SNAPSHOT</version>
    <name>springBootDemo1</name>
</project>
復(fù)制代碼

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

代碼的第一行是XML頭,指定了該xml文檔的版本和編碼方式包雀。 project是所有pom.xml的根元素宿崭,它還聲明了一些POM相關(guān)的命名空間及xsd元素。 根元素下的第一個(gè)子元素modelVersion指定了當(dāng)前的POM模型的版本才写,對(duì)于Maven3來(lái)說(shuō)葡兑,它只能是4.0.0 代碼中最重要是包含了groupId,artifactId和version了。這三個(gè)元素定義了一個(gè)項(xiàng)目基本的坐標(biāo)赞草,在Maven的世界铁孵,任何的jar、pom或者jar都是以基于這些基本的坐標(biāo)進(jìn)行區(qū)分的房资。

groupId定義了項(xiàng)目屬于哪個(gè)組,隨意命名檀头,比如谷歌公司的myapp項(xiàng)目轰异,就取名為 com.google.myapp

artifactId定義了當(dāng)前Maven項(xiàng)目在組中唯一的ID,比如定義hello-world。

version指定了項(xiàng)目當(dāng)前的版本0.0.1-SNAPSHOT,SNAPSHOT意為快照暑始,說(shuō)明該項(xiàng)目還處于開(kāi)發(fā)中搭独,是不穩(wěn)定的。

name元素生命了一個(gè)對(duì)于用戶更為友好的項(xiàng)目名稱廊镜,雖然這不是必須的牙肝,但還是推薦為每個(gè)POM聲明name,以方便信息交流

依賴的配置

<project>
...
<dependencies>
    <dependency>
        <groupId>實(shí)際項(xiàng)目</groupId>
     模塊
     <version>版本</version>
     <type>依賴類型</type>
     <scope>依賴范圍</scope>
     <optional>依賴是否可選</optional>
     <!—主要用于排除傳遞性依賴-->
     <exclusions>
         <exclusion>
           <groupId>…</groupId>
          …
       </exclusion>
     </exclusions>
  </dependency>
<dependencies>
...
</project>
復(fù)制代碼

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

根元素project下的dependencies可以包含一個(gè)或者多個(gè)dependency元素,以聲明一個(gè)或者多個(gè)項(xiàng)目依賴。每個(gè)依賴可以包含的元素有:

  • grounpId配椭、artifactId和version:以來(lái)的基本坐標(biāo)虫溜,對(duì)于任何一個(gè)依賴來(lái)說(shuō),基本坐標(biāo)是最重要的股缸,Maven根據(jù)坐標(biāo)才能找到需要的依賴衡楞。
  • type:依賴的類型,對(duì)于項(xiàng)目坐標(biāo)定義的packaging敦姻。大部分情況下瘾境,該元素不必聲明,其默認(rèn)值為jar
  • scope:依賴的范圍
  • optional:標(biāo)記依賴是否可選
  • exclusions:用來(lái)排除傳遞性依賴

依賴范圍

依賴范圍就是用來(lái)控制依賴和三種classpath(編譯classpath镰惦,測(cè)試classpath迷守、運(yùn)行classpath)的關(guān)系,Maven有如下幾種依賴范圍:

  • compile:編譯依賴范圍旺入。如果沒(méi)有指定兑凿,就會(huì)默認(rèn)使用該依賴范圍。使用此依賴范圍的Maven依賴眨业,對(duì)于編譯急膀、測(cè)試、運(yùn)行三種classpath都有效龄捡。典型的例子是spring-code,在編譯卓嫂、測(cè)試和運(yùn)行的時(shí)候都需要使用該依賴。
  • test: 測(cè)試依賴范圍聘殖。使用次依賴范圍的Maven依賴晨雳,只對(duì)于測(cè)試classpath有效,在編譯主代碼或者運(yùn)行項(xiàng)目的使用時(shí)將無(wú)法使用此依賴奸腺。典型的例子是Jnuit,它只有在編譯測(cè)試代碼及運(yùn)行測(cè)試的時(shí)候才需要餐禁。
  • provided:已提供依賴范圍。使用此依賴范圍的Maven依賴突照,對(duì)于編譯和測(cè)試classpath有效帮非,但在運(yùn)行時(shí)候無(wú)效。典型的例子是servlet-api,編譯和測(cè)試項(xiàng)目的時(shí)候需要該依賴讹蘑,但在運(yùn)行項(xiàng)目的時(shí)候末盔,由于容器以及提供,就不需要Maven重復(fù)地引入一遍座慰。
  • runtime:運(yùn)行時(shí)依賴范圍陨舱。使用此依賴范圍的Maven依賴,對(duì)于測(cè)試和運(yùn)行classpath有效版仔,但在編譯主代碼時(shí)無(wú)效游盲。典型的例子是JDBC驅(qū)動(dòng)實(shí)現(xiàn)误墓,項(xiàng)目主代碼的編譯只需要JDK提供的JDBC接口,只有在執(zhí)行測(cè)試或者運(yùn)行項(xiàng)目的時(shí)候才需要實(shí)現(xiàn)上述接口的具體JDBC驅(qū)動(dòng)益缎。
  • system:系統(tǒng)依賴范圍谜慌。該依賴與三種classpath的關(guān)系,和provided依賴范圍完全一致链峭,但是畦娄,使用system范圍的依賴時(shí)必須通過(guò)systemPath元素顯示地指定依賴文件的路徑。由于此類依賴不是通過(guò)Maven倉(cāng)庫(kù)解析的弊仪,而且往往與本機(jī)系統(tǒng)綁定熙卡,可能構(gòu)成構(gòu)建的不可移植,因此應(yīng)該謹(jǐn)慎使用励饵。systemPath元素可以引用環(huán)境變量驳癌,如:
<dependency>
    <groupId>javax.sql</groupId>
    jdbc-stdext
    <Version>2.0</Version>
    <scope>system</scope>
    <systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
復(fù)制代碼

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

  • import:導(dǎo)入依賴范圍。該依賴范圍不會(huì)對(duì)三種classpath產(chǎn)生實(shí)際的影響役听。

上述除import以外的各種依賴范圍與三種classpath的關(guān)系如下:

image.png

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

傳遞性依賴

比如一個(gè)account-email項(xiàng)目為例颓鲜,account-email有一個(gè)compile范圍的spring-code依賴,spring-code有一個(gè)compile范圍的commons-logging依賴典予,那么commons-logging就會(huì)成為account-email的compile的范圍依賴甜滨,commons-logging是account-email的一個(gè)傳遞性依賴

image.png

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

有了傳遞性依賴機(jī)制,在使用Spring Framework的時(shí)候就不用去考慮它依賴了什么瘤袖,也不用擔(dān)心引入多余的依賴衣摩。Maven會(huì)解析各個(gè)直接依賴的POM,將那些必要的間接依賴捂敌,以傳遞性依賴的形式引入到當(dāng)前的項(xiàng)目中艾扮。

依賴范圍

假設(shè)A依賴于B,B依賴于C,我們說(shuō)A對(duì)于B是第一直接依賴占婉,B對(duì)于C是第二直接依賴泡嘴,A對(duì)于C是傳遞性依賴。第一直接依賴和第二直接依賴的范圍決定了傳遞性依賴的范圍逆济,如下圖所示酌予,最左邊一行表示第一直接依賴范圍,最上面一行表示第二直接依賴范圍奖慌,中間的交叉單元格則表示傳遞依賴范圍霎终。

image.png

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

從上圖中,我們可以發(fā)現(xiàn)這樣的規(guī)律:

  • 當(dāng)?shù)诙苯右蕾嚨姆秶莄ompile的時(shí)候升薯,傳遞性依賴的范圍與第一直接依賴的范圍一致;
  • 當(dāng)?shù)诙苯右蕾嚨姆秶莟est的時(shí)候击困,依賴不會(huì)得以傳遞涎劈;
  • 當(dāng)?shù)诙苯右蕾嚨姆秶莗rovided的時(shí)候广凸,只傳遞第一直接依賴范圍也為provided的依賴,切傳遞依賴的范圍同樣為provided;
  • 當(dāng)?shù)诙苯右蕾嚨姆秶莚untime的時(shí)候蛛枚,傳遞性依賴的范圍與第一直接依賴的范圍一致谅海,但compile列外,此時(shí)傳遞性依賴范圍為runtime.

依賴調(diào)解 有時(shí)候蹦浦,當(dāng)傳遞性依賴造成為題的時(shí)候扭吁,就需要清楚地知道該傳遞性依賴是從哪條依賴路徑引入的。這就是依賴調(diào)解的作用盲镶,依賴調(diào)解有兩大原則: 1. 路徑最近者優(yōu)先 比如項(xiàng)目有A有這樣的依賴關(guān)系:A->B->C->X(1.0)侥袜、A->D->X(2.0),X是A的傳遞性依賴,但是兩條依賴路徑上有兩個(gè)版本的X溉贿,所以根據(jù)第一原則枫吧,A->D->X(2.0)路徑短,所以X(2.0)會(huì)被解析使用 2. 第一聲明者優(yōu)先 如果路徑都一樣長(zhǎng)的話宇色,第一原則就不行了九杂,比如 A->B->Y(1.0)、A->C->Y(2.0),Y(1.0)和Y(2.0)的路徑一樣宣蠕,所以這時(shí)候根據(jù)第二原則例隆,先聲明的被解析。

可選依賴

image.png

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

如圖抢蚀,項(xiàng)目中A依賴B镀层,B依賴于X和Y,如果所有這三個(gè)的范圍都是compile的話思币,那么X和Y就是A的compile范圍的傳遞性依賴鹿响,但是如果我想X,Y不作為A的傳遞性依賴,不給他用的話谷饿。就需要下面提到的配置可選依賴惶我。

<project>  
    <modelVersion>4.0.0</modelVersion>  
    <groupId>com.juvenxu.mvnbook</groupId>  
    project-b  
    <version>1.0.0</version>  
    <dependencies>  
        <dependency>  
            <groupId>mysql</groupId>  
            mysql-connector-java  
            <version>5.1.10</version>  
            <optional>true</optional>  
        </dependency>  
        <dependency>  
            <groupId>postgresql</groupId>  
            postgresql</groupId>  
            <version>8.4-701.jdbc3</version>  
            <optional>true</optional>  
        </dependency>  
    </dependencies>  
</project>  
復(fù)制代碼

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

配置也簡(jiǎn)單,在依賴?yán)锩嫣砑?/p>

<optional>true</optional>
復(fù)制代碼

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

就表示可選依賴了博投,這樣A如果想用X,Y就要直接顯示的添加依賴了绸贡。

排除依賴

有時(shí)候你引入的依賴中包含你不想要的依賴包,你想引入自己想要的毅哗,這時(shí)候就要用到排除依賴了听怕,比如下圖中spring-boot-starter-web自帶了logback這個(gè)日志包,我想引入log4j2的虑绵,所以我先排除掉logback的依賴包尿瞭,再引入想要的包就行了

image.png

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

排除依賴代碼結(jié)構(gòu):

<exclusions>
    <exclusion>
        <groupId>org.springframework.boot</groupId>
        spring-boot-starter-logging
    </exclusion>
</exclusions>
復(fù)制代碼

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

這里注意:聲明exclustion的時(shí)候只需要groupId和artifactId,而不需要version元素翅睛,這是因?yàn)橹恍枰猤roupId和artifactId就能唯一定位依賴圖中的某個(gè)依賴声搁。

歸類依賴

有時(shí)候我們引入的很多依賴包黑竞,他們都來(lái)自同一個(gè)項(xiàng)目的不同模塊,所以他們的版本號(hào)都一樣疏旨,這時(shí)候我們可以用屬性來(lái)統(tǒng)一管理版本號(hào)

<project>  
    <modelVersion>4.0.0</modelVersion>  
    <groupId>com.juven.mvnbook.account</groupId>  
    accout-email  
    <version>1.0.0-SNAPSHOT</version>  
    <properties>  
        <springframework.version>1.5.6</springframework.version>  
    </properties>  
    <dependencies>  
        <dependency>  
            <groupId>org.springframework</groupId>  
            spring-core  
            <version>${springframework.version}</version>  
        </dependency>   
        <dependency>  
            <groupId>org.springframework</groupId>  
            spring-beans  
            <version>${springframework.version}</version>  
        </dependency>         
    </dependencies>  
</project>  
復(fù)制代碼

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

如圖所示很魂,先通過(guò)

</properties>
    這里定義你先要的版本
</properties>
復(fù)制代碼

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

來(lái)定義,然后在下面依賴使用${}來(lái)引入你的屬性檐涝。

倉(cāng)庫(kù)

這節(jié)將介紹倉(cāng)庫(kù)的由來(lái)遏匆、布局、分類谁榜、配置幅聘、內(nèi)部工作機(jī)制、鏡像等概念

倉(cāng)庫(kù)的由來(lái)

在Maven世界中惰爬,任何一個(gè)依賴喊暖、插件或者項(xiàng)目構(gòu)建的輸出,都可以稱為構(gòu)件撕瞧。得益于坐標(biāo)機(jī)制陵叽,任何Maven項(xiàng)目使用任何一個(gè)構(gòu)件的方式都是完全相同的。在此基礎(chǔ)上丛版,Maven可以在某個(gè)位置統(tǒng)一存儲(chǔ)所有Maven項(xiàng)目共享的構(gòu)件巩掺,這個(gè)統(tǒng)一的位置就是倉(cāng)庫(kù)。

實(shí)際的Maven項(xiàng)目將不再各自存儲(chǔ)其依賴文件页畦,它們只需要聲明這些依賴的坐標(biāo)胖替,在需要的時(shí)候(例如,編譯項(xiàng)目的時(shí)候需要將依賴加入到classpath中)豫缨,Maven會(huì)自動(dòng)根據(jù)坐標(biāo)找到倉(cāng)庫(kù)中的構(gòu)件独令,并使用它們。

為了實(shí)現(xiàn)重用好芭,項(xiàng)目構(gòu)建完畢后可生成的構(gòu)件也可以安裝或者部署到倉(cāng)庫(kù)中燃箭,供其他項(xiàng)目使用。

倉(cāng)庫(kù)的布局

任何一個(gè)構(gòu)件都有其唯一的坐標(biāo)舍败,根據(jù)這個(gè)坐標(biāo)可以定義其在倉(cāng)庫(kù)中的唯一存儲(chǔ)路徑招狸,這便是Maven的倉(cāng)庫(kù)布局方式。 該路經(jīng)與坐標(biāo)對(duì)應(yīng)關(guān)系為groupId/artifactId/version/artifactId-version.packaging邻薯。 舉個(gè)例子裙戏,比如下面這個(gè)分頁(yè)插件依賴如下:

<dependency>
      <groupId>com.github.pagehelper</groupId>
      pagehelper-spring-boot-starter
      <version>1.1.0</version>
</dependency>
復(fù)制代碼

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

那他對(duì)應(yīng)的倉(cāng)庫(kù)的路徑就是這樣:

image.png

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

Maven倉(cāng)庫(kù)是基于簡(jiǎn)單文件系統(tǒng)存儲(chǔ)的,我們也理解其存儲(chǔ)方式厕诡、因此累榜,當(dāng)遇到一些與倉(cāng)庫(kù)相關(guān)的問(wèn)題時(shí),可以很方便的查找相關(guān)文件灵嫌,方便定位問(wèn)題信柿。

倉(cāng)庫(kù)的分類

image.png

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

本地倉(cāng)庫(kù)

一般來(lái)說(shuō)冀偶,在Maven項(xiàng)目目錄下,沒(méi)有諸如lib/這樣用來(lái)存放依賴文件的目錄渔嚷。當(dāng)Maven在執(zhí)行編譯或測(cè)試時(shí),如果需要使用依賴文件稠曼,它總是基于坐標(biāo)使用本地倉(cāng)庫(kù)的依賴文件形病。

默認(rèn)情況下,不管在Window還是Linux下霞幅,每個(gè)用戶在自己用戶目錄下都有一個(gè)路徑名為.m2/repository/的倉(cāng)庫(kù)目錄漠吻。 如果你想自定義本地倉(cāng)庫(kù)目錄地址。你可以編輯文件~/.m2/settings.xml司恳,設(shè)置localRepository元素的值為想要的倉(cāng)庫(kù)地址途乃,例如:

<settings>
<localRepository>D:\java\repository\</localRepository>
</settings>
復(fù)制代碼

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

這樣,該用戶的本地倉(cāng)庫(kù)地址就被設(shè)置成了 D:\java\repository\扔傅。 需要注意的是耍共,默認(rèn)情況下,~/.m2/settings.xml文件不存在猎塞,用戶需要從Maven安裝目錄復(fù)制$M2_HOME/conf/settings.xml文件再進(jìn)行編輯试读。

遠(yuǎn)程倉(cāng)庫(kù)-中央倉(cāng)庫(kù)

由于最原始的本地倉(cāng)庫(kù)是空的,Maven必須知道至少一個(gè)可用的遠(yuǎn)程倉(cāng)庫(kù)荠耽,才能在執(zhí)行Maven命令的時(shí)候下載到需要的構(gòu)件钩骇。中央倉(cāng)庫(kù)就是這樣一個(gè)默認(rèn)的遠(yuǎn)程倉(cāng)庫(kù),Maven的安裝文件自帶了中央倉(cāng)庫(kù)的配置铝量。

中央倉(cāng)庫(kù)包含了這個(gè)世界上絕大多數(shù)流行的開(kāi)源Java構(gòu)件倘屹,以及源碼、作者信息慢叨、SCM,信息纽匙、許可證信息等,每個(gè)月這里都會(huì)接受全世界Java程序員大概1億次的訪問(wèn)插爹,它對(duì)全世界Java開(kāi)發(fā)者的貢獻(xiàn)由此可見(jiàn)一斑哄辣。

遠(yuǎn)程倉(cāng)庫(kù)-私服

私服是一種特殊的遠(yuǎn)程倉(cāng)庫(kù),它是架設(shè)在局域網(wǎng)內(nèi)的倉(cāng)庫(kù)服務(wù)赠尾,私服代理廣域網(wǎng)上的遠(yuǎn)程倉(cāng)庫(kù)力穗,供局域網(wǎng)內(nèi)的Maven用戶使用。當(dāng)Maven需要下載構(gòu)件的時(shí)候气嫁,它從私服請(qǐng)求当窗,如果私服上不存在該構(gòu)件,則從外部的遠(yuǎn)程倉(cāng)庫(kù)下載寸宵,緩存在私服上之后崖面,再為Maven的下載請(qǐng)求提供服務(wù)元咙。因此,一些無(wú)法從外部倉(cāng)庫(kù)下載到的構(gòu)件也能從本地上傳到私服上供大家使用巫员。 私服的好處:

  • 節(jié)省自己的外網(wǎng)速度
  • 加速M(fèi)aven構(gòu)建
  • 部署第三方構(gòu)建
  • 提高穩(wěn)定性庶香,增強(qiáng)控制
  • 降低中央倉(cāng)庫(kù)的負(fù)荷

遠(yuǎn)程倉(cāng)庫(kù)的配置

在平時(shí)的開(kāi)發(fā)中,我們往往不會(huì)使用默認(rèn)的中央倉(cāng)庫(kù)简识,默認(rèn)的中央倉(cāng)庫(kù)訪問(wèn)的速度比較慢赶掖,訪問(wèn)的人或許很多,有時(shí)候也無(wú)法滿足我們項(xiàng)目的需求七扰,可能項(xiàng)目需要的某些構(gòu)件中央倉(cāng)庫(kù)中是沒(méi)有的奢赂,而在其他遠(yuǎn)程倉(cāng)庫(kù)中有,如JBoss Maven倉(cāng)庫(kù)颈走。這時(shí)膳灶,可以在pom.xml中配置該倉(cāng)庫(kù),代碼如下:

<!-- 配置遠(yuǎn)程倉(cāng)庫(kù) -->
    <repositories>
        <repository>
            <id>jboss</id>
            <name>JBoss Repository</name>
            <url>http://repository.jboss.com/maven2/</url>
            <releases>
                <enabled>true</enabled>
                <updatePolicy>daily</updatePolicy>
            </releases>
            <snapshots>
                <enabled>false</enabled>
                <checksumPolicy>warn</checksumPolicy>
            </snapshots>
            <layout>default</layout>
        </repository>
    </repositories>
復(fù)制代碼

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

  • repository:在repositories元素下立由,可以使用repository子元素聲明一個(gè)或者多個(gè)遠(yuǎn)程倉(cāng)庫(kù)轧钓。
  • id:倉(cāng)庫(kù)聲明的唯一id,尤其需要注意的是拆吆,Maven自帶的中央倉(cāng)庫(kù)使用的id為central聋迎,如果其他倉(cāng)庫(kù)聲明也使用該id,就會(huì)覆蓋中央倉(cāng)庫(kù)的配置枣耀。
  • name:倉(cāng)庫(kù)的名稱霉晕,讓我們直觀方便的知道倉(cāng)庫(kù)是哪個(gè),暫時(shí)沒(méi)發(fā)現(xiàn)其他太大的含義捞奕。
  • url:指向了倉(cāng)庫(kù)的地址牺堰,一般來(lái)說(shuō),該地址都基于http協(xié)議颅围,Maven用戶都可以在瀏覽器中打開(kāi)倉(cāng)庫(kù)地址瀏覽構(gòu)件伟葫。
  • releases和snapshots:用來(lái)控制Maven對(duì)于發(fā)布版構(gòu)件和快照版構(gòu)件的下載權(quán)限。需要注意的是enabled子元素院促,該例中releases的enabled值為true筏养,表示開(kāi)啟JBoss倉(cāng)庫(kù)的發(fā)布版本下載支持,而snapshots的enabled值為false常拓,表示關(guān)閉JBoss倉(cāng)庫(kù)的快照版本的下載支持渐溶。根據(jù)該配置,Maven只會(huì)從JBoss倉(cāng)庫(kù)下載發(fā)布版的構(gòu)件弄抬,而不會(huì)下載快照版的構(gòu)件茎辐。
  • layout:元素值default表示倉(cāng)庫(kù)的布局是Maven2及Maven3的默認(rèn)布局,而不是Maven1的布局⊥下剑基本不會(huì)用到Maven1的布局弛槐。
  • 其他:對(duì)于releases和snapshots來(lái)說(shuō),除了enabled依啰,它們還包含另外兩個(gè)子元素updatePolicy和checksumPolicy乎串。

1:元素updatePolicy用來(lái)配置Maven從遠(yuǎn)處倉(cāng)庫(kù)檢查更新的頻率,默認(rèn)值是daily速警,表示Maven每天檢查一次灌闺。其他可用的值包括:never-從不檢查更新;always-每次構(gòu)建都檢查更新坏瞄;interval:X-每隔X分鐘檢查一次更新(X為任意整數(shù))。
2:元素checksumPolicy用來(lái)配置Maven檢查校驗(yàn)和文件的策略甩卓。當(dāng)構(gòu)建被部署到Maven倉(cāng)庫(kù)中時(shí)鸠匀,會(huì)同時(shí)部署對(duì)應(yīng)的檢驗(yàn)和文件。在下載構(gòu)件的時(shí)候逾柿,Maven會(huì)驗(yàn)證校驗(yàn)和文件缀棍,如果校驗(yàn)和驗(yàn)證失敗,當(dāng)checksumPolicy的值為默認(rèn)的warn時(shí)机错,Maven會(huì)在執(zhí)行構(gòu)建時(shí)輸出警告信息爬范,其他可用的值包括:fail-Maven遇到校驗(yàn)和錯(cuò)誤就讓構(gòu)建失敗弱匪;ignore-使Maven完全忽略校驗(yàn)和錯(cuò)誤青瀑。

遠(yuǎn)程倉(cāng)庫(kù)的認(rèn)證

大部分的遠(yuǎn)程倉(cāng)庫(kù)不需要認(rèn)證,但是如果是自己內(nèi)部使用萧诫,為了安全起見(jiàn)斥难,還是要配置認(rèn)證信息的。 配置認(rèn)證信息和配置遠(yuǎn)程倉(cāng)庫(kù)不同帘饶,遠(yuǎn)程倉(cāng)庫(kù)可以直接在pom.xml中配置哑诊,但是認(rèn)證信息必須配置在settings.xml文件中。這是因?yàn)閜om往往是被提交到代碼倉(cāng)庫(kù)中供所有成員訪問(wèn)的及刻,而settings.xml一般只存在于本機(jī)镀裤。因此,在settings.xml中配置認(rèn)證信息更為安全缴饭。

<settings>
 2     ...
 3     <!--配置遠(yuǎn)程倉(cāng)庫(kù)認(rèn)證信息-->
 4     <servers>
 5         <server>
 6             <id>releases</id>
 7             <username>admin</username>
 8             <password>admin123</password>
 9         </server>
10     </servers>
11     ...
12 </settings>
復(fù)制代碼

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

這里除了配置賬號(hào)密碼之外暑劝,值關(guān)鍵的就是id了,這個(gè)id要跟你在pom.xml里面配置的遠(yuǎn)程倉(cāng)庫(kù)repository的id一致茴扁,正是這個(gè)id將認(rèn)證信息與倉(cāng)庫(kù)配置聯(lián)系在了一起铃岔。

部署構(gòu)件至遠(yuǎn)程倉(cāng)庫(kù)

我們自己搭建遠(yuǎn)程倉(cāng)庫(kù)的目的就是為了可以方便部署我們自己項(xiàng)目的構(gòu)件以及一些無(wú)法從外部倉(cāng)庫(kù)直接獲取的構(gòu)件。這樣才能在開(kāi)發(fā)時(shí),供其他對(duì)團(tuán)隊(duì)成員使用毁习。 Maven除了能對(duì)項(xiàng)目進(jìn)行編譯智嚷、測(cè)試、打包之外纺且,還能將項(xiàng)目生成的構(gòu)件部署到遠(yuǎn)程倉(cāng)庫(kù)中盏道。首先,需要編輯項(xiàng)目的pom.xml文件载碌。配置distributionManagement元素猜嘱,代碼如下:

<distributionManagement>
        <repository>
            <id>releases</id>
            <name>public</name>
            <url>http://59.50.95.66:8081/nexus/content/repositories/releases</url>
        </repository>
        <snapshotRepository>
            <id>snapshots</id>
            <name>Snapshots</name>
            <url>http://59.50.95.66:8081/nexus/content/repositories/snapshots</url>
        </snapshotRepository>
</distributionManagement>
復(fù)制代碼

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

看代碼,從命名上就看的出來(lái)區(qū)別嫁艇,repository表示表示發(fā)布版本(穩(wěn)定版本)構(gòu)件的倉(cāng)庫(kù)朗伶,snapshotRepository表示快照版本(開(kāi)發(fā)測(cè)試版本)的倉(cāng)庫(kù)。這兩個(gè)元素都需要配置id步咪、name和url论皆,id為遠(yuǎn)程倉(cāng)庫(kù)的唯一標(biāo)識(shí),name是為了方便人閱讀猾漫,關(guān)鍵的url表示該倉(cāng)庫(kù)的地址点晴。

配置好了就運(yùn)行命令mvn clean deploy批狐,Maven就會(huì)將項(xiàng)目構(gòu)建輸出的構(gòu)件部署到配置對(duì)應(yīng)的遠(yuǎn)程倉(cāng)庫(kù)峭竣,如果項(xiàng)目當(dāng)前的版本是快照版本,則部署到快照版本的倉(cāng)庫(kù)地址牙丽,否則就部署到發(fā)布版本的倉(cāng)庫(kù)地址禽翼。 當(dāng)前項(xiàng)目是快照還是發(fā)布版本是通過(guò) true 這個(gè)來(lái)區(qū)分的屠橄。忘記的同學(xué)在看看上面的## 遠(yuǎn)程倉(cāng)庫(kù)的配置。

鏡像

如果倉(cāng)庫(kù)X可以提供倉(cāng)庫(kù)Y存儲(chǔ)的所有內(nèi)容捐康,那么就可以認(rèn)為X是Y的一個(gè)鏡像仇矾。用過(guò)Maven的都知道,國(guó)外的中央倉(cāng)庫(kù)用起來(lái)太慢了解总,所以選擇一個(gè)國(guó)內(nèi)的鏡像就很有必要贮匕,我推薦國(guó)內(nèi)的阿里云鏡像。 阿里云鏡像:配置很簡(jiǎn)單花枫,修改conf文件夾下的settings.xml文件刻盐,添加如下鏡像配置:

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

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

上例子中,的值為central,表示該配置為中央庫(kù)的鏡像劳翰,任何對(duì)于中央倉(cāng)庫(kù)的請(qǐng)求都會(huì)轉(zhuǎn)至該鏡像敦锌,用戶也可以用同樣的方法配置其他倉(cāng)庫(kù)的鏡像

這里介紹下<mirrorOf>配置的各種選項(xiàng)

  • <mirrorOf>*<mirrorOf>:匹配所有遠(yuǎn)程倉(cāng)庫(kù)。
  • <mirrorOf>external:*<mirrorOf>:匹配所有遠(yuǎn)程倉(cāng)庫(kù)佳簸,使用localhost的除外乙墙,使用file://協(xié)議的除外颖变。也就是說(shuō),匹配所有不在本機(jī)上的遠(yuǎn)程倉(cāng)庫(kù)听想。
  • <mirrorOf>repo1,repo2<mirrorOf>:匹配倉(cāng)庫(kù)repo1h和repo2腥刹,使用逗號(hào)分隔多個(gè)遠(yuǎn)程倉(cāng)庫(kù)。
  • <mirrorOf>*,!repo1<mirrorOf>:匹配所有遠(yuǎn)程倉(cāng)庫(kù)汉买,repo1除外衔峰,使用感嘆號(hào)將倉(cāng)庫(kù)從匹配中排除。

需要注意的是蛙粘,由于鏡像倉(cāng)庫(kù)完全屏蔽了被鏡像倉(cāng)庫(kù)垫卤,當(dāng)鏡像倉(cāng)庫(kù)不穩(wěn)定或者停止服務(wù)的時(shí)候,Maven仍將無(wú)法訪問(wèn)被鏡像倉(cāng)庫(kù)出牧,因而將無(wú)法下載構(gòu)件穴肘。

倉(cāng)庫(kù)服務(wù)搜索

這里介紹2個(gè)提供倉(cāng)庫(kù)服務(wù)搜索的地址:

總結(jié)

暫時(shí)先這樣,后面繼續(xù)補(bǔ)充更新本篇舔痕,關(guān)于私服搭建的會(huì)另外開(kāi)一片介紹梢褐。 本篇基于《Maven實(shí)戰(zhàn)》整理提煉。需要電子書(shū)小伙伴可關(guān)注博主微信公眾號(hào):嘟爺java超神學(xué)堂(java2Learn)回復(fù)關(guān)鍵字 maven獲取電子書(shū)赵讯。

作者:嘟嘟MD
鏈接:https://juejin.cn/post/6844903543711907848
來(lái)源:稀土掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)耿眉,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處边翼。

<!-- 配置聚合 -->
<modules>
    <!-- 指定各個(gè)子工程的相對(duì)路徑 -->
    <module>starfish-learn-grpc</module>
    <module>starfish-learn-kafka</module>
    <module>starfish-web-demo</module>
</modules>

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

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市懂牧,隨后出現(xiàn)的幾起案子侈净,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畜侦,死亡現(xiàn)場(chǎng)離奇詭異元扔,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)夏伊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門摇展,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人溺忧,你說(shuō)我怎么就攤上這事咏连。” “怎么了鲁森?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵祟滴,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我歌溉,道長(zhǎng)垄懂,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任痛垛,我火速辦了婚禮草慧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匙头。我一直安慰自己漫谷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布蹂析。 她就那樣靜靜地躺著舔示,像睡著了一般。 火紅的嫁衣襯著肌膚如雪电抚。 梳的紋絲不亂的頭發(fā)上惕稻,一...
    開(kāi)封第一講書(shū)人閱讀 51,115評(píng)論 1 296
  • 那天,我揣著相機(jī)與錄音蝙叛,去河邊找鬼俺祠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛借帘,可吹牛的內(nèi)容都是我干的锻煌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼姻蚓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼宋梧!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起狰挡,我...
    開(kāi)封第一講書(shū)人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤捂龄,失蹤者是張志新(化名)和其女友劉穎释涛,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體倦沧,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡唇撬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了展融。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窖认。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖告希,靈堂內(nèi)的尸體忽然破棺而出扑浸,到底是詐尸還是另有隱情,我是刑警寧澤燕偶,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布喝噪,位于F島的核電站,受9級(jí)特大地震影響指么,放射性物質(zhì)發(fā)生泄漏酝惧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一伯诬、第九天 我趴在偏房一處隱蔽的房頂上張望晚唇。 院中可真熱鬧,春花似錦盗似、人聲如沸缺亮。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至葵礼,卻和暖如春号阿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鸳粉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工扔涧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人届谈。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓枯夜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親艰山。 傳聞我的和親對(duì)象是個(gè)殘疾皇子湖雹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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