Maven 入門教程

Maven 這個詞能夠翻譯爲專家的意思。它是由 Apache 組織的開源,主要服務 Java 平臺項目的構建、依賴管理和項目信息管理。php

有了 Maven 咱們只需編寫一些配置而後運行一條命令就能夠自動完成項目編譯、測試、打包、發佈等流程。前端

安裝

Maven 須要依賴 Java 環境,因此首先要確認安裝了 Java,首先去官網下載 Maven,而後就能夠把它隨便解壓到一個文件夾,並把這個文件夾路徑設置爲 M2_HOME 環境變量,最後將 %M2_HOME%\bin(Windows)加入到 PATH,Linux 爲 export PATH=$PATH:$M2_HOME/binjava

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, artifactIdversion 定義了一個項目的基本座標。

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 下。

咱們的包名也應該和 groupIdartifactId 相吻合。

而後執行

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 它是根據 artifactIdversion 還有打包類型進行命名。

test 會自動幫咱們執行 compilepackage 會自動幫咱們執行 testinstall 會自動幫咱們執行 packageinstall 是將項目安裝到倉庫中。

咱們還可使用 archetype 插件來生成項目骨架,執行 mvn archetype:generate 命令就能夠了,固然也可使用編輯器新建一個 Maven 項目來選擇項目模板。

座標

Maven 是經過座標找到一個依賴的,而一組座標是經過一些元素定義的。

  • groupId 一個組織的的一個實際項目
  • artifactId 實際項目中的一個 Maven 項目或模塊
  • version 版本
  • packaging 打包方式有 jarwar
  • classifier 用來定義構建輸出的附屬構建 如 hello-world-1.0.0-javadoc.jar,它裏面包含了 Java 文檔,javadoc 就是就是附屬構建的 classifier

前三個必須定義,packaging 默認 jarclassifier 不能直接定義。

依賴

一個項目依賴須要放在 dependencies 中,dependency 有幾個子元素。

  • groupId, artifactIdversion 是項目基本座標。
  • 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),可是 BC 定義爲可選的,那麼依賴就不會被傳遞。依賴可選能夠經過 <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>
複製代碼

若是咱們本地有兩個項目 AB ,項目 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 就是倉庫地址,releasessnapshots 分別用來控制發佈版和快照版構件的下載,enabledtrue 表示開啓下載,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 LATESTSNAPSHOT 時會根據更新策略去全部遠程倉庫搜尋構件元數據,而後和本地的元數據合併,再經過合併後的值取尋找版本。

鏡像

咱們還能夠在 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 套生命週期,分別是 cleandefaultsite,Maven 的生命週期是抽象的存在,就像一個接口,它把實際工做交給個插件。這 3 套生命週期是相互獨立的。

每一個生命週期都有一些階段(phase),如 clean 生命週期有 3 個階段,pre-clean, cleanpost-clean,階段是有順序的,當執行 clean 階段,會執行它前面的 pre-clean

clean 生命週期的階段一共有

  1. pre-clean 執行清理前須要執行的工做
  2. clean 清理上次構件
  3. post-clean 清理事後須要執行的操做

default 生命週期是最核心的部分,它一共有以下階段

  1. validate
  2. initialize
  3. generate-sources
  4. process-sources 處理主資源文件,通常是 src/main/resources 目錄下的文件。
  5. generate-resources
  6. process-resources
  7. compile 編譯項目源碼。
  8. process-classes
  9. generate-test-sources
  10. process-test-sources 處理項目測試資源文件。
  11. generate-test-resources
  12. process-test-resources
  13. test-compile 編譯測試源碼
  14. process-test-classes
  15. test 使用單元測試框架運行測試。
  16. prepare-package
  17. package 接受編譯好的代碼,打包成可發佈格式。
  18. pre-integration-test
  19. integration-test
  20. post-integration-test
  21. verify
  22. install 將包安裝到 Maven 本地倉庫,供本地其餘項目使用
  23. deploy 將包複製到遠程倉庫。

site 生命週期目的是創建和發佈項目站點。

  1. pre-site 生成站點以前要執行的操做
  2. site 生成項目站點文檔
  3. post-site 執行生成站點以後要完成的工做
  4. site-deploy 將站點發布到服務器

命令行

執行 Maven 任務主要方式就是調用 Maven 的生命週期階段。

mvn clean 就是執行 clean 生命週期的 clean 階段

mvn test 就是執行 default 生命週期的 test 階段

mvn clean install 就是執行 clean 生命週期 clean 階段和 defaultinstall 階段。

插件目標

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-pluginjar-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 查到對應的插件呢?

由於 dependencymaven-dependency-plugin 插件的前綴,Maven 能夠經過前綴查找到對應的 artifactId。Maven 會經過本地倉庫查找插件,若是查不到就會取遠程倉庫查找。

對於未指定 groupId 的插件,Maven 會默認使用 org.apache.maven.plugins 做爲它的 groupId。Maven 在超級POM 中設定了核心插件的版本,咱們項目中就能夠繼承到這些版本的設定,而無需本身設置。

若是一個插件既不是核心插件又沒有設定版本,那麼會檢查全部倉庫可用版本,而後作出選擇。

聚合與繼承

Maven 還支持多模塊開發,咱們一個項目可能有不少的模塊,Maven 能夠將它們聚合在一塊兒。

假如咱們有一個項目 app,它分爲 a、b 和 c 三個模塊,也就是三個 Maven 項目,由於它們是一個項目因此它們的 groupIdversion 都是同樣的。

咱們項目目錄可能像下面這樣。

|-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 並計算出模塊的構建次序,而後順序執行。

繼承

咱們發現咱們的子模塊有不少相同的配置,這時候咱們就可使用繼承來消除重複。

咱們能夠再建立一個用來作 parentpom.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 咱們也能夠省略它。

如今咱們繼承了父級的 groupIdversion,若是咱們須要不一樣的值,也能夠覆蓋它。幾乎全部的項目均可以繼承父級的。

若是咱們父級聲明瞭一個依賴,那麼全部子模塊都會繼承這個依賴,即便有的模塊不須要這個依賴。

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 屬性

Maven pom.xml 中可使用 ${} 來注入屬性,它一共支持 6 類屬性。

  • 內置屬性,如 ${version} 項目版本 和 ${basedir} 項目根目錄
  • POM 屬性,能夠引用 pom.xml 中的屬性,如 ${project.version}, ${project.build.sourceDirectory}
  • 自定義屬性,在 properties 中自定義的屬性
  • settings.xml 中的屬性,如 ${settings.loaclRepository}
  • Java 系統屬性,如 ${user.name}
  • 環境變量,如 ${JAVA_HOME}

Profile

咱們項目中開發環境和線上環境不一樣每每須要不一樣的配置。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

有時候咱們須要將前端和後端放在一塊兒,咱們就可使用 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>
複製代碼

它會本身安裝全新的 nodenpm ,與全局的 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

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

相關文章
相關標籤/搜索