Maven 這個詞能夠翻譯爲專家的意思。它是由 Apache 組織的開源,主要服務 Java 平臺項目的構建、依賴管理和項目信息管理。php
有了 Maven 咱們只需編寫一些配置而後運行一條命令就能夠自動完成項目編譯、測試、打包、發佈等流程。前端
Maven 須要依賴 Java 環境,因此首先要確認安裝了 Java,首先去官網下載 Maven,而後就能夠把它隨便解壓到一個文件夾,並把這個文件夾路徑設置爲 M2_HOME
環境變量,最後將 %M2_HOME%\bin
(Windows)加入到 PATH
,Linux 爲 export PATH=$PATH:$M2_HOME/bin
。java
mvn -v # 在命令行運行這條命令,查看 Maven 版本
複製代碼
對於升級就是重複上面的流程。node
Maven 安裝目錄下的 conf
文件下存放着 Maven 的配置 settings.xml
,它的做用域是全局的,咱們能夠複製它到 ~/.m2
下,用戶目錄下的 settings.xml
修改只對當前的用戶有做用。Maven 的依賴包倉庫放在,~/.m2
文件夾下的 repository
文件夾中。git
由於 Maven 實際上執行的是 Java 命令,咱們能夠經過 MAVEN_OPT
環境變量設置它的參數。一般須要設置它的值爲 -Xms128m -Xmx512m
由於對於大點的項目可能出現內存不夠的錯誤。github
對於編輯器中的 Maven 咱們能夠設置它使用咱們下載的 Maven,這樣就能夠避免兩個 Maven 版本不一致而形成的構建行爲不一致。web
對於 Maven 項目,最核心的就是 pom.xml
(Project Object Model) 咱們須要把項目的構建配置信息都寫在裏面。spring
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>hello-world</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello world project</name>
<description>Demo project</description>
</project>
複製代碼
第一行是 XML 頭,指定了 XML 版本和文件編碼。sql
而後就是 project
元素,它是配置文件的根元素,它還聲明瞭 POM 的命名空間。docker
而後就是 modelVersion
對於 Maven2 和 Maven3 它只能是 4.0.0
版本。
groupId
, artifactId
和 version
定義了一個項目的基本座標。
groupId
定義了項目屬於哪一個組,它一般和 Java 中包名命名同樣,例如 a
公司啓動了一個 myapp
項目,那麼他的 groupId
就多是 com.a.myapp
。
artifactId
定義了當前 Maven 項目在組中惟一的 ID,由於一個項目可能有多個子項目或模塊。
version
指定了當前項目的版本。SNAPSHOT
爲快照版本。
name
給項目更友好的名稱,description
是對項目的描述。
上面這些字段定義了項目基本的信息,下面咱們就能夠編寫項目代碼了。
package com.demo.helloworld;
public class HelloWorld {
public String sayHello() {
return "hello world";
}
public static void main(String[] args) {
System.out.println(sayHello());
}
}
複製代碼
Maven 採用約定大於配置的方式,在大多數的狀況下項目源碼應該放在項目文件夾下的 src/main/java
下(Maven 會自動在該目錄下搜尋源碼),資源放在 src/main/resources
下,測試代碼放在 src/test/java
下。
咱們的包名也應該和 groupId
和 artifactId
相吻合。
而後執行
mvn clean compile
複製代碼
clean
是讓 Maven 清除項目輸出 target
目錄。compile
任務用來將項目編譯到 target/classes
目錄下。
而後咱們用 JUnit 編寫單元測試,首先須要在 pom.xml
加上 junit 的依賴。
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>hello-world</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello world project</name>
<description>Demo project</description>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
複製代碼
引入一個依賴咱們須要填寫它的基本座標,有了這個座標,Maven 就會自動取中央倉庫下載,這個依賴到 ~/.m2/repository
文件夾下。
scope test
是表示依賴只對測試有效,在主代碼中引入 junit 會報錯。
package com.demo.helloworld;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class HelloWorldTest {
@Test
public void test() {
HelloWorld helloWorld = new HelloWorld();
assertEquals("hello world", helloWorld.sayHello());
}
}
複製代碼
而後咱們須要對 Maven 的編譯插件進行一些配置,由於它默認只支持 Java 1.5 因此咱們須要配置它爲更高版本的 Java
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>hello-world</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello world project</name>
<description>Demo project</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 配置源碼編碼 -->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- 配置 Java 版本 -->
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
複製代碼
而後執行
mvn clean test
複製代碼
它會編譯測試文件而後運行測試,最後咱們就可以看到測試經過的輸出。
下一步就是對項目打包,由於咱們沒有指定項目打包的類型,因此默認就是 jar
。
mvn clean package
複製代碼
進行打包以前 Maven 會自動幫咱們編譯,測試,經過了就打成 jar
包,放在 target
目錄下,名稱爲 hello-world-0.0.1-SNAPSHOT.jar
它是根據 artifactId
和 version
還有打包類型進行命名。
test
會自動幫咱們執行 compile
, package
會自動幫咱們執行 test
,install
會自動幫咱們執行 package
, install
是將項目安裝到倉庫中。
咱們還可使用 archetype
插件來生成項目骨架,執行 mvn archetype:generate
命令就能夠了,固然也可使用編輯器新建一個 Maven 項目來選擇項目模板。
Maven 是經過座標找到一個依賴的,而一組座標是經過一些元素定義的。
groupId
一個組織的的一個實際項目artifactId
實際項目中的一個 Maven 項目或模塊version
版本packaging
打包方式有 jar
,war
等classifier
用來定義構建輸出的附屬構建 如 hello-world-1.0.0-javadoc.jar
,它裏面包含了 Java 文檔,javadoc
就是就是附屬構建的 classifier
。前三個必須定義,packaging
默認 jar
,classifier
不能直接定義。
一個項目依賴須要放在 dependencies
中,dependency
有幾個子元素。
groupId
, artifactId
和 version
是項目基本座標。type
依賴類型,默認是 jar
scope
依賴範圍optional
是否可選exclusions
用來排除傳遞依賴其中依賴範圍有幾個值能夠選。依賴範圍主要是控制編譯
, 測試
和 運行
的 classpath
compile
默認,在編譯,測試和運行都有效test
只對測試 classpath 有效,如 junit 它只要在測試的時候能用到就行。provided
對編譯和測試有效,好比 servlet-api
,由於運行時容器都會提供,因此無需重複引入。runtime
運行時依賴,對測試和運行時有效,在編譯時無效,好比 jdbc 驅動實現,只有在須要運行的時候在須要特定的驅動實現。system
系統依賴範圍,它與 provided
依賴範圍徹底一致,只是它的依賴必須使用 systemPath
顯式的指定依賴路徑,它不是經過 Maven 倉庫解析。<dependencies>
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
</dependencies>
複製代碼
還有一種 import
爲導入依賴範圍,不會對上面三個依賴範圍產生影響。
傳遞依賴就是好比咱們依賴 spring-core
(compile) 可是 spring-core
依賴 commons-logging
(compile),那麼咱們的項目也依賴 commons-logging
(compile)。有了這個機制,咱們就不用考慮 spring
依賴什麼,沒必要手動安裝它的依賴,Maven 會自動將必要的間接依賴引入當前項目。spring boot 的起步依賴就是利用 Maven 的傳遞依賴。
依賴範圍也會對傳遞依賴產生影響。
左側表示直接依賴,上面是表明間接依賴,中間就表示傳遞依賴範圍。
好比咱們項目傳遞依賴中有兩個依賴是同樣的可是它的版本不同,那麼 Maven 就會看誰的路徑最短,最短的優先。
若是它們是同樣長的,Maven 就查看 POM 中的依賴聲明誰在前面誰就優先。
若是咱們項目依賴 A
(compile),A
依賴 B
(compile) 和 C
(compile),可是 B
和 C
定義爲可選的,那麼依賴就不會被傳遞。依賴可選能夠經過 <optional>true</optional>
指定。
若是咱們想排除一個傳遞依賴,好比 spring boot 默認是使用的 jackson,若是咱們想用 gson,那麼咱們就能夠將 jackason 排除,而後顯式的引入 gson。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
</dependencies>
複製代碼
若是咱們依賴一個項目的不少模塊,由於是一個項目因此版本號都是同樣的,這樣咱們就要給每一個依賴填寫同樣的版本號,升級的話又要一個一個的改。
這時候咱們就能夠聲明一個變量,而後其餘地方直接使用就好了。
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>hello-world</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello world project</name>
<description>Demo project</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>2.5.6</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- · · · -->
</dependencies>
</project>
複製代碼
${}
能夠引入 Maven 的屬性。
Maven 中任何一個項目或插件的輸出都稱爲構件。任何構件都會有一個惟一的座標。爲了重用 Maven 的依賴都統一放在倉庫中,而不是每一個項目都有個 lib
同樣的文件夾來裝它的依賴。
Maven 的倉庫分爲遠程倉庫和本地倉庫,Maven 會首先經過座標去本地倉庫尋找依賴,若是沒有就去遠程倉庫下載依賴,而後在放入本地倉庫再使用。若是都沒有的話那麼就會報錯。
咱們能夠自定義遠程倉庫,Maven 自帶了一個遠程倉庫,它包含絕大部分的構件,默認狀況都會去這個中央倉庫下載構件。
私服是另外一種遠程倉庫,爲了節約寬帶和時間,在局域網中搭建一個私有倉庫,用其代理外部遠程倉庫,內部項目還能夠安裝到私服上供其餘項目使用。
除了上面兩種還有其餘的公開遠程倉庫。好比 jboss repository 等。
本地倉庫默認位置是當前用戶目錄下的 .m2/repository
文件夾,若是咱們想更改它的位置能夠修改 .m2/settings.xml
文件。
<settings>
<localRepository>D:\maven\repository</localRepository>
</settings>
複製代碼
若是咱們本地有兩個項目 A
和 B
,項目 B
依賴於 A
,那麼咱們能夠將項目 A
安裝到本地倉庫,這樣咱們就能夠在 B
項目中依賴 A
了,咱們能夠在 A
項目中執行 mvn clean install
來將 A
項目安裝到本地倉庫。
Maven 須要知道最少一個遠程倉庫,這樣 Maven 才能下載構件到本地。中央倉庫就是默認的遠程倉庫,全部 Maven 項目 pom.xml
會繼承一個超級POM,它就在 Maven 安裝目錄下的 lib/maven-model-builder-3.6.1.jar\org\apache\maven\model\
文件夾,名爲 pom-4.0.0.xml
。
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories>
<!-- · · · -->
</project>
複製代碼
私服是特殊遠程倉庫,它代理多個外部遠程倉庫,咱們使用私服來下載構件,私服上若是沒有就會取遠程下載,而後緩存起來。
若是咱們須要的構件不在中央倉庫而在另一個倉庫,咱們就能夠在 pom.xml
中配置該倉庫。
<repositories>
<repository>
<id>jboss</id>
<name>JBoss Repository</name>
<url>http://repository.jboss.org/maven2/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
複製代碼
其中 id
必須時惟一的,若是有倉庫聲明和中央倉庫同樣的 id 就會覆蓋它,url
就是倉庫地址,releases
和 snapshots
分別用來控制發佈版和快照版構件的下載,enabled
爲 true
表示開啓下載,false
表示關閉下載。
快照版本是表示開發中的版本,開發中項目會平凡的變化,好比咱們開發一個項目中一個模塊,可是它要依賴另外一個模塊,咱們就將它安裝到本地依賴,這樣就能夠在咱們項目中使用,可是若是依賴項目變了,可是咱們仍是會使用緩存本地的模塊,這時候就要使用 snapshot
版本了,對於快照版本 Maven 每次會去檢查當前是否是最新的,若是不是就下載最新的代碼。
snapshots
能夠設置 Maven 檢查更新頻率。
<snapshots>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</snapshots>
複製代碼
never
從不,always
每次構件都去檢查,daily
天天(默認值)。
checksumPolicy
是 Maven 下載構件時會校驗構件,默認時 warn
警告,還有 fail
項目構建會失敗,ignore
忽略。
對於組織內部的倉庫每每須要認證才運行訪問,咱們能夠在 settings.xml
中設置倉庫的帳號和密碼。
<servers>
<id>repo</id>
<username>username</username>
<password>password</password>
</servers>
複製代碼
其中 id
和咱們定義遠程倉庫 id
對應。
私服的一個做用就是用來部署第三方構件,Maven 能夠幫助咱們將構件部署到倉庫中。
<project>
<distributionManagement>
<repository>
<id>id</id>
<name>Release Repository</name>
<url>http://196.0.0.1/path/to/release</url>
</repository>
<snapshotRepository>
<id>snapshot</id>
<name>Snapshot Repository</name>
<url>http://196.0.0.2/path/to/release</url>
</snapshotRepository>
</distributionManagement>
</project>
複製代碼
repository
表示發佈版的倉庫,snapshotRepository
表示快照倉庫,id 是惟一標識,咱們能夠經過它來設置帳號和密碼。
而後咱們能夠執行以下命令發佈
mvn clean deploy
複製代碼
當依賴返回是 system
時 Maven 回去本地尋找。
當是顯式版構件時 如 1.2
, 1.3-beta-1
等,Maven 會去全部遠程倉庫下載到本地。
當依賴版本是 RELEASE
LATEST
和 SNAPSHOT
時會根據更新策略去全部遠程倉庫搜尋構件元數據,而後和本地的元數據合併,再經過合併後的值取尋找版本。
咱們還能夠在 settings.xml
中設置鏡像鏡像服務器。
<mirrors>
<mirror>
<id>maven.net.cn</id>
<name> maven central mirror</name>
<url>http://maven.net.cn/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
複製代碼
咱們上面給中央倉庫設置一個鏡像,咱們也能夠設置 mirrorOf
爲 *
表示匹配全部遠程倉庫。
Maven 有 3 套生命週期,分別是 clean
、default
和 site
,Maven 的生命週期是抽象的存在,就像一個接口,它把實際工做交給個插件。這 3 套生命週期是相互獨立的。
每一個生命週期都有一些階段(phase),如 clean
生命週期有 3 個階段,pre-clean
, clean
和 post-clean
,階段是有順序的,當執行 clean
階段,會執行它前面的 pre-clean
。
clean
生命週期的階段一共有
pre-clean
執行清理前須要執行的工做clean
清理上次構件post-clean
清理事後須要執行的操做default
生命週期是最核心的部分,它一共有以下階段
validate
initialize
generate-sources
process-sources
處理主資源文件,通常是 src/main/resources
目錄下的文件。generate-resources
process-resources
compile
編譯項目源碼。process-classes
generate-test-sources
process-test-sources
處理項目測試資源文件。generate-test-resources
process-test-resources
test-compile
編譯測試源碼process-test-classes
test
使用單元測試框架運行測試。prepare-package
package
接受編譯好的代碼,打包成可發佈格式。pre-integration-test
integration-test
post-integration-test
verify
install
將包安裝到 Maven 本地倉庫,供本地其餘項目使用deploy
將包複製到遠程倉庫。site
生命週期目的是創建和發佈項目站點。
pre-site
生成站點以前要執行的操做site
生成項目站點文檔post-site
執行生成站點以後要完成的工做site-deploy
將站點發布到服務器執行 Maven 任務主要方式就是調用 Maven 的生命週期階段。
mvn clean
就是執行 clean
生命週期的 clean
階段
mvn test
就是執行 default
生命週期的 test
階段
mvn clean install
就是執行 clean
生命週期 clean
階段和 default
的 install
階段。
Maven 只是定義了生命週期,然而實際的工做仍是要交給插件。一個插件會有一個或多個目標(goal)每一個目標對應一個功能,如 surefire:test
surefire
是插件名,test
是插件目標,surefire
是 Maven 默認測試插件。
Maven 的生命週期的階段和插件的目標相互綁定,來完成實際任務。
Maven 默認爲主要的生命週期階段綁定了不少插件目標,當調用生命週期階段時,相應的插件就會被執行。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
複製代碼
上面咱們將 maven-source-plugin
的 jar-no-fork
目標綁定到了 verify
階段。id 爲任務名。
插件也有參數,咱們能夠經過命令行或在 pom.xml
設置它的參數。
咱們能夠經過 -D參數鍵=參數值
來設置插件目標參數,如 mvn package -Dmaven.test.skip=true
-D
是 Java 自帶的,用來設置 Java 系統屬性,Maven 只是重用了該參數。
在 pom.xml
中咱們能夠經過 configuration
設置參數。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
複製代碼
除了在外層設置插件參數(全局),咱們還能夠對一個 execution
設置參數。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>ant-validate</id>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>lalala</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
複製代碼
咱們還能夠經過命令行調用插件目標。
mvn [options] [goal<s>] [phase[s]]
複製代碼
由於有些插件目標不適合綁定到生命週期階段執行,因此咱們能夠直接在命令行執行插件的目標。
mvn dependency:tree # 查看項目依賴
# 固然咱們將插件的 groupId artifactId version 都寫上
複製代碼
咱們知道插件有它的基本座標,Maven 是如何經過 dependency
查到對應的插件呢?
由於 dependency
是 maven-dependency-plugin
插件的前綴,Maven 能夠經過前綴查找到對應的 artifactId
。Maven 會經過本地倉庫查找插件,若是查不到就會取遠程倉庫查找。
對於未指定 groupId
的插件,Maven 會默認使用 org.apache.maven.plugins
做爲它的 groupId
。Maven 在超級POM 中設定了核心插件的版本,咱們項目中就能夠繼承到這些版本的設定,而無需本身設置。
若是一個插件既不是核心插件又沒有設定版本,那麼會檢查全部倉庫可用版本,而後作出選擇。
Maven 還支持多模塊開發,咱們一個項目可能有不少的模塊,Maven 能夠將它們聚合在一塊兒。
假如咱們有一個項目 app,它分爲 a、b 和 c 三個模塊,也就是三個 Maven 項目,由於它們是一個項目因此它們的 groupId
,version
都是同樣的。
咱們項目目錄可能像下面這樣。
|-app
|- a
|- src
|- pom.xml
|- b
|- src
|- pom.xml
|- c
|- src
|- pom.xml
pom.xml
複製代碼
咱們最外層有一個 pom.xml
,咱們用它來聚合項目中的模塊。
<?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.demo.app</groupId>
<artifactId>app-aggregator</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>a</module>
<module>b</module>
<module>c</module>
</modules>
</project>
複製代碼
須要將 packaging
設置爲 pom
,而後設定它要聚合的模塊。
module
中是模塊的相對路徑,若是和其餘模塊是平行目錄則路徑就是 ../a
等。
如今咱們就不用一個一個取構件了,咱們在最外層執行 mvn clean install
。Maven 會解析 pom.xml
並計算出模塊的構建次序,而後順序執行。
咱們發現咱們的子模塊有不少相同的配置,這時候咱們就可使用繼承來消除重複。
咱們能夠再建立一個用來作 parent
的 pom.xml
也能夠重用咱們上面建立的 aggregator
pom.xml
,若是重用的話咱們就無需修改它,可是須要修改要繼承它的模塊。
<!-- a 模塊 -->
<?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>
<artifactId>app-a</artifactId>
<parent>
<groupId>com.demo.app</groupId>
<artifactId>app-aggregator</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
</project>
複製代碼
咱們使用 parent
來指明模塊要繼承的父級。這裏的 relativePath
的默認值就是 ../pom.xml
咱們也能夠省略它。
如今咱們繼承了父級的 groupId
和 version
,若是咱們須要不一樣的值,也能夠覆蓋它。幾乎全部的項目均可以繼承父級的。
若是咱們父級聲明瞭一個依賴,那麼全部子模塊都會繼承這個依賴,即便有的模塊不須要這個依賴。
Maven 提供了 dependencyManagement
來讓子模塊不會引入實際依賴,只有子模塊聲明纔會依賴。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-autoconfigure</artifactId>
<version>2.1.7.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
複製代碼
<!-- a 模塊 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
</dependencies>
複製代碼
有了 dependencyManagement
,咱們子模塊不會直接繼承,可是若是聲明瞭須要繼承就無需填寫依賴的版本了。
spring boot 就是利用 Maven 的繼承,我許讓咱們本身填寫依賴的版本。
還有一個 pluginManagement
(在 build
元素下) 它的做用和 dependencyManagement
是同樣的,只是它是做用於插件。
Maven 的測試是使用 maven-surefire-plugin
插件。
有時候咱們想跳過測試能夠在命令行加入 -DskipTests
,-Dmaven.test.skip=true
不只跳過測試,也會跳過測試代碼的編譯。
咱們還能夠運行指定測試,如 -Dtest=*Tests
表示只運行 Tests
結尾的測試,*
匹配 0 或多個字符。還可使用 ,
分割多個參數,如 -Dtest=*Tests,*IT
。
Maven pom.xml
中可使用 ${}
來注入屬性,它一共支持 6 類屬性。
${version}
項目版本 和 ${basedir}
項目根目錄pom.xml
中的屬性,如 ${project.version}
, ${project.build.sourceDirectory}
等properties
中自定義的屬性settings.xml
中的屬性,如 ${settings.loaclRepository}
。${user.name}
${JAVA_HOME}
咱們項目中開發環境和線上環境不一樣每每須要不一樣的配置。Maven 中的 Profile
就能夠針對環境的不一樣使用不一樣的配置。
db.url=${db.url}
db.password=${db.password}
複製代碼
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault> <!-- 配置默認激活 -->
</activation>
<properties>
<db.url>dev.url</db.url>
<db.password>dev.password</db.password>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<db.url>prod.url</db.url>
<db.password>prod.password</db.password>
</properties>
</profile>
</profiles>
<!-- 須要資源開啓過濾,這樣上面 properties 文件的 ${} 就能夠注入咱們的 properties 中屬性了 -->
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
</build>
複製代碼
而後咱們就能夠在命令行中使用 -Pdev
來激活開發模式的配置,profile
中的配置是當激活當前 profile
纔會生效的配置。
有時候咱們須要將前端和後端放在一塊兒,咱們就可使用 frontend-maven-plugin , 來幫助咱們安裝 node npm 或 yarn 來執行 npm script。
咱們只須要在前端模塊中添加這個插件
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend-maven-plugin.version}</version>
<configuration>
<installDirectory>target</installDirectory> <!-- node 安裝目錄 -->
<nodeVersion>v13.6.0</nodeVersion>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>npm lint</id>
<goals>
<goal>npm</goal>
</goals>
<phase>compile</phase>
<configuration>
<arguments>run lint</arguments>
</configuration>
</execution>
<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<phase>compile</phase>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
<execution>
<id>npm run test</id>
<goals>
<goal>npm</goal>
</goals>
<phase>test</phase>
<configuration>
<arguments>run test</arguments>
</configuration>
</execution>
</executions>
</plugin>
複製代碼
它會本身安裝全新的 node
和 npm
,與全局的 node
隔離。而後咱們使用它的 npm
goal 來執行 npm 命令。 咱們也可使用 clean 插件來清理每次生成的代碼。
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>${maven-clean-plugin.version}</version>
<executions>
<execution>
<id>remove existing output</id>
<phase>compile</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<fileset>
<directory>build</directory>
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>
複製代碼
dockerfile-maven-plugin
插件能夠幫助咱們構建和發佈 docker 鏡像,而無需再手動輸入命令。
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>${dockerfile-maven-version}</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
</goals>
<configuration>
<contextDirectory>context</contextDirectory> <!-- 上下文目錄 默認是當前目錄 -->
<dockerfile>not-context/Dockerfile</dockerfile> <!-- Dockerfile 地址,默認是當前目錄下的 Dockerfile -->
<buildArgs> <!-- docker build 命令參數 -->
<IMAGE_VERSION>0.0.1</IMAGE_VERSION>
</buildArgs>
</configuration>
</execution>
<execution>
<id>tag</id>
<goals>
<goal>tag</goal>
</goals>
<configuration>
<repository>test/build-tag-version</repository> <!-- image 名稱 -->
<tag>${project.version}</tag> <!-- tag 版本 -->
<skip>true</skip> <!-- 若是想跳過能夠設置skip 爲 true -->
</configuration>
</execution>
</executions>
</plugin>
複製代碼
咱們須要一個 Dockerfile 來構建咱們的 image,若是是 spring boot 項目能夠簡單使用 fat jar 方法來構建。
FROM openjdk:8-jdk-alpine
VOLUME /tmp COPY target/*.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"] 複製代碼
更多關於 spring boot docker 能夠查看 Spring Boot Docker。