前言
當我們在開發專案時,有時需要用到外部依賴組件,例如當我們需要Json序列化的時候需要用到FastJson組件,我們可以通過下載對應jar包加載到專案中,但當一個大的專案同時需要依賴各種各樣的外部服務,就存在著配置繁瑣、依賴沖突等問題,因此可以通過maven來完成對應的依賴管理功能,
一、Settings配置
settings.xml用來配置maven專案中的各種引數檔案,包括本地倉庫、遠程倉庫、私服、認證等資訊,
1.1 配置概述
1.1.1 全域settings、用戶setting、pom的區別
- 全域 settings.xml 是 maven 的全域組態檔,一般位于${maven.home}/conf/settings.xml,即maven檔案夾下的conf中,
- 用戶 setting是maven的用戶組態檔,一般位于${user.home}/.m2/settings.xml,即每位用戶都有一份組態檔,
- pom.xml 檔案是專案組態檔,一般位于專案根目錄下或子目錄下,
配置優先級從高到低:pom.xml > 本地 settings > 全域 settings
如果這些檔案同時存在,在應用配置時,會合并它們的內容,如果有重復的配置,優先級高的配置會覆寫優先級低的,
1.1.2 倉庫【重要】
如前言所述,我們依賴的外部服務是需要有地方進行存盤的,而存盤的地方就稱之為倉庫,其中倉庫又分為本地倉庫、中央倉庫、鏡像倉庫、私服,
其對應關系為:
(1)本地倉庫
當專案在本地編譯或運行時,直接加載本地的依賴服務無疑是最快的,默認情況下,不管在Window還是Linux下,每個用戶在自己用戶目錄下都有一個路徑名為.m2/repository/的倉庫目錄,
而原始的本地倉庫是為空的,因此maven需要知道一個網路上的倉庫,在本地倉庫不存在時前往下載網路上的倉庫,也就是遠程倉庫,
(2)中央倉庫
當maven未配置時,會默認請求maven的中央倉庫,中央倉庫包含了這個世界上絕大多數流行的開源java構件,以及原始碼、作者資訊、SCM,資訊、許可證資訊等,每個月這里都會接受全世界java程式員大概1億次的訪問,它對全世界java開發者的貢獻由此可見一斑,
但是由于最常見的例如網路原因等,國外的中央倉庫使用起來并不順利,因此就有了下載地址為國內的中央倉庫,也就是鏡像倉庫,
(3)鏡像倉庫
總結來說,鏡像倉庫就是將國外的中心倉庫復制一份到國內,這樣一來下載速度以及訪問速度都將很快,
(4)私服
一般來說中央倉庫或者鏡像倉庫都能滿足我們的需求,但是當我們在公司內合作開發代碼時,可能因為系統保密性原因,有一些其他同事開發的外部依賴只希望能夠被本公司的人使用,而如果上傳到鏡像倉庫則保密性就不復存在了,因此私服最主要的功能時存盤一些公司內部不希望被公開的依賴服務,
1.2 settings配置詳解
settings.xml配置了本地全域maven的相關配置,
以下是一份seetings.xml的檔案配置頂級元素,
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>
<interactiveMode>
<usePluginRegistry>
<offline>
<pluginGroups>
<servers>
<mirrors>
<proxies>
<profiles>
<activeProfiles>
</settings>
1.2.1 localRepository
用來標識本地倉庫的位置
D:/Maven/Repository
1.2.2 interactiveMode
maven 是否需要和用戶互動以獲得輸入,默認為true,
true
1.2.3 usePluginRegistry
maven 是否需要使用 plugin-registry.xml 檔案來管理插件版本,
false
1.2.4 offline
用來標識是否以離線模式運營maven,
當系統不能聯網時,可以通過次配置來離線運行,
false
1.2.5 servers
當使用maven私服時,某些私服需要配置認證資訊,需要在此處填寫相應的配置,之所以不寫在pom.xml中是因為一般專案在上傳至代碼倉庫時同樣會將pom.xml上傳,而setting.xml一般位于用戶本地,因此相對比較安全,
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
...
<!--配置服務端的一些設定,一些設定如安全證書不應該和pom.xml一起分發,這種型別的資訊應該存在于構建服務器上的settings.xml檔案中, -->
<servers>
<!--服務器元素包含配置服務器時需要的資訊 -->
<server>
<!--這是server的id(注意不是用戶登陸的id),該id與distributionManagement中repository元素的id相匹配, -->
<id>server001</id>
<!--鑒權用戶名,鑒權用戶名和鑒權密碼表示服務器認證所需要的登錄名和密碼, -->
<username>my_login</username>
<!--鑒權密碼 ,鑒權用戶名和鑒權密碼表示服務器認證所需要的登錄名和密碼,密碼加密功能已被添加到2.1.0 +,詳情請訪問密碼加密頁面 -->
<password>my_password</password>
<!--鑒權時使用的私鑰位置,和前兩個元素類似,私鑰位置和私鑰密碼指定了一個私鑰的路徑(默認是${user.home}/.ssh/id_dsa)以及如果需要的話,一個密語,將來passphrase和password元素可能會被提取到外部,但目前它們必須在settings.xml檔案以純文本的形式宣告, -->
<privateKey>${usr.home}/.ssh/id_dsa</privateKey>
<!--鑒權時使用的私鑰密碼, -->
<passphrase>some_passphrase</passphrase>
<!--檔案被創建時的權限,如果在部署的時候會創建一個倉庫檔案或者目錄,這時候就可以使用權限(permission),這兩個元素合法的值是一個三位數字,其對應了unix檔案系統的權限,如664,或者775, -->
<filePermissions>664</filePermissions>
<!--目錄被創建時的權限, -->
<directoryPermissions>775</directoryPermissions>
</server>
</servers>
...
</settings>
1.2.6 mirrors【重要】
用來配置相應的鏡像倉庫,
如果倉庫X可以提供倉庫Y存盤的所有內容,那么就可以認為X是Y的一個鏡像,用過Maven的都知道,國外的中央倉庫因為網路原因用起來太慢了,所以選擇一個國內的鏡像就很有必要,我推薦國內的阿里云鏡像, 阿里云鏡像:配置很簡單,修改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>
<mirror>
<id>alimaven1</id>
<name>aliyun maven1</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
其中id與name用來標識唯一的倉庫,url為鏡像倉庫地址,mirrorOf用來匹配當請求什么倉庫依賴時使用該鏡像,
這里介紹下<mirrorOf>
配置的各種選項
<mirrorOf>*<mirrorOf>
:匹配所有遠程倉庫,<mirrorOf>external:*<mirrorOf>
:匹配所有遠程倉庫,使用localhost的除外,使用file://協議的除外,也就是說,匹配所有不在本機上的遠程倉庫,<mirrorOf>repo1,repo2<mirrorOf>
:匹配倉庫repo1h和repo2,使用逗號分隔多個遠程倉庫,<mirrorOf>*,!repo1<mirrorOf>
:匹配所有遠程倉庫,repo1除外,使用感嘆號將倉庫從匹配中排除,
需要注意的是,由于鏡像倉庫完全屏蔽了被鏡像倉庫,當鏡像倉庫不穩定或者停止服務的時候,Maven仍將無法訪問被鏡像倉庫,因而將無法下載構件,
此外, maven 讀取mirror 配置是 從上往下讀取的,因此謹慎配置<mirrorOf>*<mirrorOf>
,因為如果第一個鏡像倉庫配置了如此標志,那么如果該倉庫即使不存在對應依賴也不會向下游查詢,
1.2.7 proxies
用來配置代理,
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
...
<proxies>
<!--代理元素包含配置代理時需要的資訊 -->
<proxy>
<!--代理的唯一定義符,用來區分不同的代理元素, -->
<id>myproxy</id>
<!--該代理是否是激活的那個,true則激活代理,當我們宣告了一組代理,而某個時候只需要激活一個代理的時候,該元素就可以派上用處, -->
<active>true</active>
<!--代理的協議, 協議://主機名:埠,分隔成離散的元素以方便配置, -->
<protocol>http</protocol>
<!--代理的主機名,協議://主機名:埠,分隔成離散的元素以方便配置, -->
<host>proxy.somewhere.com</host>
<!--代理的埠,協議://主機名:埠,分隔成離散的元素以方便配置, -->
<port>8080</port>
<!--代理的用戶名,用戶名和密碼表示代理服務器認證的登錄名和密碼, -->
<username>proxyuser</username>
<!--代理的密碼,用戶名和密碼表示代理服務器認證的登錄名和密碼, -->
<password>somepassword</password>
<!--不該被代理的主機名串列,該串列的分隔符由代理服務器指定;例子中使用了豎線分隔符,使用逗號分隔也很常見, -->
<nonProxyHosts>*.google.com|ibiblio.org</nonProxyHosts>
</proxy>
</proxies>
...
</settings>
1.2.8 profiles【重要】
根據環境引數來調整構建配置的串列,用于定義一組profile
seetings中的profile
是 pom.xml
中 profile
元素的裁剪版本,
它包含了id
、activation
、repositories
、pluginRepositories
和 properties
元素,這里的 profile 元素只包含這五個子元素是因為這里只關心構建系統這個整體(這正是 settings.xml 檔案的角色定位),而非單獨的專案物件模型設定,如果一個 settings.xml
中的 profile
被激活,它的值會覆寫任何其它定義在 pom.xml
中帶有相同 id 的 profile
,
(1)repositories
定義了一組遠程倉庫的串列,當該屬性對應的profile被激活時,會使用該遠程倉庫,
<repositories>
<!--包含需要連接到遠程倉庫的資訊 -->
<repository>
<!--遠程倉庫唯一標識 -->
<id>codehausSnapshots</id>
<!--遠程倉庫名稱 -->
<name>Codehaus Snapshots</name>
<!--如何處理遠程倉庫里發布版本的下載 -->
<releases>
<!--true或者false表示該倉庫是否為下載某種型別構件(發布版,快照版)開啟, -->
<enabled>false</enabled>
<!--該元素指定更新發生的頻率,Maven會比較本地POM和遠程POM的時間戳,這里的選項是:always(一直),daily(默認,每日),interval:X(這里X是以分鐘為單位的時間間隔),或者never(從不), -->
<updatePolicy>always</updatePolicy>
<!--當Maven驗證構件校驗檔案失敗時該怎么做-ignore(忽略),fail(失敗),或者warn(警告), -->
<checksumPolicy>warn</checksumPolicy>
</releases>
<!--如何處理遠程倉庫里快照版本的下載,有了releases和snapshots這兩組配置,POM就可以在每個單獨的倉庫中,為每種型別的構件采取不同的策略,例如,可能有人會決定只為開發目的開啟對快照版本下載的支持,參見repositories/repository/releases元素 -->
<snapshots>
<enabled />
<updatePolicy />
<checksumPolicy />
</snapshots>
<!--遠程倉庫URL,按protocol://hostname/path形式 -->
<url>http://snapshots.maven.codehaus.org/maven2</url>
<!--用于定位和排序構件的倉庫布局型別-可以是default(默認)或者legacy(遺留),Maven 2為其倉庫提供了一個默認的布局;然而,Maven 1.x有一種不同的布局,我們可以使用該元素指定布局是default(默認)還是legacy(遺留), -->
<layout>default</layout>
</repository>
</repositories>
(2)properties
定義了一組拓展屬性,當對應的profile被激活時該屬性有效,
<!--
1. env.X: 在一個變數前加上"env."的前綴,會回傳一個shell環境變數,例如,"env.PATH"指代了$path環境變數(在Windows上是%PATH%),
2. project.x:指代了POM中對應的元素值,例如: <project><version>1.0</version></project>通過${project.version}獲得version的值,
3. settings.x: 指代了settings.xml中對應元素的值,例如:<settings><offline>false</offline></settings>通過 ${settings.offline}獲得offline的值,
4. java System Properties: 所有可通過java.lang.System.getProperties()訪問的屬性都能在POM中使用該形式訪問,例如 ${java.home},
5. x: 在<properties/>元素中,或者外部檔案中設定,以${someVar}的形式使用,
-->
<properties>
<user.install>${user.home}/our-project</user.install>
</properties>
(3)id
全域唯一標識,如果一個 settings.xml
中的 profile
被激活,它的值會覆寫任何其它定義在 pom.xml
中帶有相同 id 的 profile
,
(4)pluginRepositories
同repositories差不多,不過該標簽定義的是插件的遠程倉庫,
(5)activation
觸發激活該profile的條件,
<activation>
<!--profile默認是否激活的標識 -->
<activeByDefault>false</activeByDefault>
<!--當匹配的jdk被檢測到,profile被激活,例如,1.4激活JDK1.4,1.4.0_2,而!1.4激活所有版本不是以1.4開頭的JDK, -->
<jdk>1.5</jdk>
<!--當匹配的作業系統屬性被檢測到,profile被激活,os元素可以定義一些作業系統相關的屬性, -->
<os>
<!--激活profile的作業系統的名字 -->
<name>Windows XP</name>
<!--激活profile的作業系統所屬家族(如 'windows') -->
<family>Windows</family>
<!--激活profile的作業系統體系結構 -->
<arch>x86</arch>
<!--激活profile的作業系統版本 -->
<version>5.1.2600</version>
</os>
<!--如果Maven檢測到某一個屬性(其值可以在POM中通過${name}參考),其擁有對應的name = 值,Profile就會被激活,如果值欄位是空的,那么存在屬性名稱欄位就會激活profile,否則按區分大小寫方式匹配屬性值欄位 -->
<property>
<!--激活profile的屬性的名稱 -->
<name>mavenVersion</name>
<!--激活profile的屬性的值 -->
<value>2.0.3</value>
</property>
<!--提供一個檔案名,通過檢測該檔案的存在或不存在來激活profile,missing檢查檔案是否存在,如果不存在則激活profile,另一方面,exists則會檢查檔案是否存在,如果存在則激活profile, -->
<file>
<!--如果指定的檔案存在,則激活profile, -->
<exists>${basedir}/file2.properties</exists>
<!--如果指定的檔案不存在,則激活profile, -->
<missing>${basedir}/file1.properties</missing>
</file>
</activation>
1.2.9 ActiveProfiles
在運行時手工激活的profile,
該元素包含了一組 activeProfile
元素,每個 activeProfile
都含有一個 profile id,任何在 activeProfile
中定義的 profile id,不論環境設定如何,其對應的 profile
都會被激活,如果沒有匹配的 profile
,則什么都不會發生,
<activeProfiles>
<!-- 要激活的profile id -->
<activeProfile>env-test</activeProfile>
</activeProfiles>
1.2.10 激活profile的三種方式【重要】
上面有提到了兩種激活的profile的方式,還有一種可以通過命令列激活profile,
(1)通過ActiveProfiles激活
如題1.2.9
可以同時激活多個profile,
(2)通過activation結果
如題1.2.8 (5)
(3)通過命令列的方式激活
也是我們經常使用的方式,例如:
mvn -P
我們可以通過在pom.xml或setting.xml中指定不同環境的profile,在編譯構建不同的專案時,通過上述的命令列方式激活對應的profIle,例如在開發環境下:
mvn package -P dev
可以打包開環環境下的專案,
1.3 Q&A
1.3.1 mirrors與repositories的關系【重要】
從勺ò干以看到,repository標簽與mirror標簽都定義了一個遠程倉庫的位置,那么當一個依賴同時存在于兩個倉庫時,會先加載那個依賴呢?
這里需要闡述一下maven加載真正起作用的repository的步驟,
- 首先獲取pom.xml中repository的集合,然后獲取setting.xml中mirror中元素,
- 如果repository的
id
和mirror的mirrorOf
的值相同,則該mirror替代該repository, - 如果該repository找不到對應的mirror,則使用其本身,
- 依此可以得到最終起作用的repository集合,可以理解mirror是復寫了對應id的repository,
mirror相當于一個攔截器,會攔截被mirrorOf
匹配到的repository,匹配原則參照 1.2.6
,在匹配到后,會用mirror里定義的url替換到repository,
沒有配置mirror
配置了mirror
二、Pom.xml詳解
上章中setting.xml定義了某個環境下全域專案的相關依賴配置,而pom.xml則具體定義了某一個專案中的依賴配置,
2.1 pom元素
2.1.1 基本資訊
<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>
<!-- 公司或者組織的唯一標志,也是打包成jar包路徑的依據 -->
<!-- 例如com.companyname.project-group,maven打包jar包的路徑:/com/companyname/project-group -->
<groupId>com.companyname.project-group</groupId>
<!-- 專案的唯一ID,一個groupId下面可能多個專案,就是靠artifactId來區分的 -->
<artifactId>project</artifactId>
<!-- 專案當前版本,格式為:主版本.次版本.增量版本-限定版本號 -->
<version>1.0</version>
<!--專案產生的構件型別,
jar、war主要用來標識專案打包出的服務是jar包還是war包
pom一般用作多moudle的專案中 頂層的pom用來指定子moudle中需要依賴的版本 詳見2.1.3 -->
<packaging>jar</packaging>
<!--定義了本專案的名稱與example的網址 -->
<name>itoken dependencies</name>
<url>www.funtl.com</url>
</project>
基本資訊都比較易懂,主要定義了本專案的相關配置說明,例如唯一坐標、版本、專案介紹等,
2.1.2 dependencies【重要】
(1)dependencies
本元素定義了專案中所需要的相關依賴資訊,也是最重要的元素之一,
<!--該元素描述了專案相關的所有依賴, 這些依賴自動從專案定義的倉庫中下載 -->
<dependencies>
<dependency>
<!------------------- 依賴坐標 ------------------->
<!--依賴專案的坐標三元素:groupId + artifactId + version -->
<!--其中三要素的來源就是2.1.1中別人定義好的相關資訊 -->
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>3.8.1</version>
<!------------------- 依賴傳遞 ------------------->
<!--依賴排除,即告訴maven只依賴指定的專案,不依賴該專案的這些依賴,此元素主要用于解決版本沖突問題 -->
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
<!-- 可選依賴,用于阻斷依賴的傳遞性,如果在專案B中把C依賴宣告為可選,那么依賴B的專案中無法使用C依賴 -->
<optional>true</optional>
<!------------------- 依賴范圍 ------------------->
<!--依賴范圍,在專案發布程序中,幫助決定哪些構件被包括進來
- compile:默認范圍,適用于所有階段,會隨著專案一起發布;
- runtime: 在執行時需要使用,如JDBC驅動,適用運行和測驗階段,不同于例如fastjson,需要在編譯時使用;
- test: 只在測驗時使用,用于編譯和運行測驗代碼,例如junit,不同于junit,在發布時并不需要;
- optional: 當專案自身被依賴時,標注依賴是否傳遞,用于連續依賴時使用 -->
<scope>test</scope>
</dependency>
</dependencies>
(2)如何解決依賴傳遞問題或jar包版本沖突問題
解決上述問題一般有兩種方式:
- 當我們作為依賴服務提供者時,可以通過
<optional>
標簽排除掉不想被傳遞的服務,
<!-- Project A -->
<project>
...
<dependencies>
<!-- declare the dependency to be set as optional -->
<dependency>
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
<version>1.0</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>
我們的A服務中參考了外部的依賴B服務,此時有A -> B,在別人參考我們時有C -> A ->B,若此時我們A在提供對外服務時不想讓別人依賴B服務,可以在參考B時添加<optional>
標簽為true
,這樣帶C依賴于A時并不會引入B,如果C在此時想要使用B的相關服務,需要在C的pom中顯示的呼叫B的相關服務,
- 當我們作為依賴服務使用者時,可以通過
<exclusions>
來去除掉我們依賴包中所不想依賴的其他服務,
如果此時我們的A服務依賴于B服務,B服務依賴于C服務,則有A ->B ->C,因為某種原因例如jar包沖突,我們在A中并不想依賴于C服務的版本,可以在呼叫B服務時去除掉C的相關依賴,然后自己再在A中使用C的相關版本,
<project>
...
<dependencies>
<dependency>
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<!-- 排除掉B中C的相關依賴 -->
<groupId>sample.ProjectC</groupId>
<artifactId>Project-C</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 自己參考C的相關版本 -->
<dependency>
<groupId>sample.ProjectC</groupId>
<artifactId>Project-C</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
</project>
2.1.3 <dependencyManagement>
當一個服務中存在有多個moudle
時,每個子module
都可能參考了相同的jar包,但是如果將版本維護到子module
的pom中,當需要升級時需要修改所有的pom檔案版本,maven提供了繼承的方式來解決此問題,
<!--在父pom中定義子pom需要的相關依賴 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</dependencyManagement>
在父pom的 <dependencyManagement>
中定義子pom需要的依賴及版本,
<!--在子pom中 如下定義了父pom中相關依賴資訊 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<!--因為參考了父pom 所以可以不指定版本 maven會自動去父pom中查找指定版本 此處為1.0.0 -->
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
</dependencies>
當我們的pom中有定義父pom的元素后,可以在指定需要的依賴時不指定其版本,maven會幫我們去父pom中查找相關的版本資訊,
2.1.4 properties
properties主要用來定義常量,通過${value}來使用,
<!--配置依賴版本-->
<properties>
<!-- Environment Settings -->
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Spring cloud Settings -->
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
<spring-boot-admin.version>2.0.1</spring-boot-admin.version>
<zipkin.version>2.10.1</zipkin.version>
</properties>
<dependencies>
<!--spring cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--zipkin-->
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin</artifactId>
<version>${zipkin.version}</version>
</dependency>
<dependencies>
此外,maven還通過約定大于配置的方式定義了一些常用的屬性,
屬性 | 定義 |
---|---|
${basedir} | 存放pom.xml和所有的子目錄 |
${basedir}/src/main/java | 專案的java源代碼 |
${basedir}/src/main/resources | 專案的資源,比如說property檔案,springmvc.xml |
${basedir}/src/main/webapp/WEB-INF | web應用檔案目錄,web專案的資訊,比如存放web.xml、本地圖片、jsp視圖頁面 |
${basedir}/target | 打包輸出目錄 |
${project.version} | 專案版本 |
${project.groupId} | 專案groupid |
2.1.5 resources
resources
標簽用來標識專案在編譯運行時需要額外編譯的檔案,例如手工引入jar包、不同運行環境對應不同的profile,
<build>
<resources>
<!--首先將默認resources目錄下的所有檔案包括 -->
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<!--只編譯所有以.fxml結尾的檔案 -->
<includes>
<include>**/*.fxml</include>
</includes>
<!--排除掉所有的yaml檔案 -->
<excludes>
<exclude>**/*.yaml</exclude>
</excludes>
</resource>
<!--將不同環境下對應的不同yaml或properties檔案編譯運行 -->
<resource>
<!--
<directory>src/main/profiles/dev</directory>
<directory>src/main/profiles/beta<directory>
<directory>src/main/profiles/pre</directory>
-->
<directory>src/main/profiles/product</directory>
<filtering>true</filtering>
<includes>
<include>**/*.fxml</include>
</includes>
</resource>
<!--將手工引入的jar包編譯運行 -->
<resource>
<directory>lib</directory>
<targetPath>BOOT-INF/lib/</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
</resources>
</build>
2.1.6 profile
與setting.xml中profile所不同的是(參照1.2.8),pom中的profile有著更多的標簽來描述一組環境,從作用上來區分的話,一般setting.xml用來標識不同的遠程倉庫,而pom中的profile一般用來標識當前專案屬于什么環境,如下是一組常見的pom中的profiles,
<profiles>
<profile>
<id>dev</id>
<!--激活條件 其中默認為該profile 更多激活條件可以參考1.2.8 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<!--當此profile被激活時,會將 project.active 的屬性賦值為dev -->
<properties>
<project.active>dev</project.active>
</properties>
</profile>
<profile>
<id>test</id>
<!--當此profile被激活時,會將 project.active 的屬性賦值為test -->
<properties>
<project.active>test</project.active>
</properties>
</profile>
</profiles>
<resources>
<resource>
<!--根據不同的環境 project.active 取得不同的值 從而會將不同的環境下的yaml或properties檔案編譯進項目中 達到只需要在編譯時指定環境變數即可 不用每次都要修改組態檔 -->
<directory>src/main/${project.active}</directory>
<filtering>true</filtering>
<includes>
<include>**/*.fxml</include>
</includes>
</resource>
</resources>
此外,一般通過 mvn -P dev/beta/pre/product
命令來激活不同的環境,也可以通過其他的方式來激活profile,詳見1.2.10,
當然,pom中的profile不止有指定編譯環境的功能,同樣也可以指定遠程倉庫等其他功能,
2.1.6 modules
當我們專案中有多個模塊時,如果我們要單獨打包的話需要在每一個模塊都執行對應的maven命令,但是通過<modules>
標簽可以將子服務或平級服務進行聚合,只需要打包該服務,也就會將其對應的子模塊同時打包,
<modules>
<!-- 引入子模塊所在的相對目錄 -->
<module>springmybatis</module>
<!-- 引入同級模塊所在的相對目錄 -->
<module>../utils</module>
</modules>
三、null:jrdp-common:null:jar問題解決
3.1包找不到問題
我們某次在開發功能的時候,在我們的專案中參考了伏羲另外一個系統的jar包,但是預發環境下編譯的時候卻發現構建失敗,原因是
因為當時專案有用到京東自己的倉庫,所以我們當時第一反應是去倉庫中查找,結果發現倉庫中是有這個jar包的,
在發現并不是最常見的jar包不存在的問題后,我們開始分析報錯原因,發現報錯的 jrdp-common
這個包并不是我們直接參考的,而是在我們參考的jar包中參考的,并且 null:jrdp-common:null:jar
可以推測前面應該是 groupID
與 version
,
假設我們的專案是A專案,參考的專案是B專案,也就是 A->B->jrdp-common
于是我們打開B專案,查看B的pom結構,
發現B專案的pom中確實參考了jrdp-common
這個包,但是并沒有指定版本,是因為繼承了 xx-parent
這個包,我們在這個包中確實也找到了指定的版本號,因此就排除了專案中沒有指定groupid與版本號的問題,
這個時候好像就問題就陷入了思路,但是我們注意到,我們之前另一個私服上也是有這個包的,那么之前的在另一個私服上參考好像是沒有問題的,我們查看了私服了上的pom檔案,發現也是跟專案一樣的,
然后我們就突然想到,會不會是倉庫中的包有問題,果不其然
沒有指定parent也沒有指定版本號,于是我們修改了這個版本的pom,至此問題解決,
總結:因為我們的系統已經被好多個團隊中轉接手過,因此可能在某些地方踩了不少坑,像這種問題應該就是之前的團隊上傳了一些有問題的jar包,導致依賴不可用,但是因為我們之前一直用的私服是沒有什么問題的,只到這次用到了倉庫問題才浮現,
另外,此問題并不具有普適性,但是當遇到了groupid不能未空的時候可以按照此方法進行排查,
作者:京東科技 韓國凱
內容來源:京東云開發者社區
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556009.html
標籤:其他
下一篇:返回列表