你肯定 Maven 相關的東西所有了解嗎

前言

若是你對 Maven 的瞭解只停留在怎麼添加依賴包,你真的須要看接下來的內容。php

<dependencies>
    <!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
    <dependency>
        <groupId>org.openjdk.jol</groupId>
        <artifactId>jol-core</artifactId>
        <version>0.10</version>
    </dependency>
</dependencies>
複製代碼
  • maven 包的依賴關係、依賴傳遞及依賴傳遞遵循的規則
  • 依賴包的做用域
  • 怎麼解決 jar 包衝突
  • 項目繼承和聚合
  • maven 生命週期
  • maven 插件使用及經常使用命令
  • maven 私服的使用
  • 怎麼發佈 jar
  • maven 定義不一樣的配置環境
  • maven-assembly-plugin 打包

Maven

目前 java 項目流行的項目管理工具 MavenGradle。目前使用率來講,Maven 使用佔比是高於 Gradle 的。糾結選哪一個管理工具的時候就用 Maven 就行。java

Maven 中經過 POM-Project Object Model 項目對象模型的概念來管理項目。在 Maven 中每一個項目都至關於一個對象,對象(項目)之間能夠依賴、繼承、聚合。mysql

項目依賴包查找網站 mvnrepository.comgit

依賴包放在 Maven 倉庫中,咱們須要經過依賴的座標信息,從倉庫中下載 jar 。spring

座標信息:groupId,artifactId,versionsql

當咱們在 pom.xml 引入某個 a.jar , Maven 會從本地倉庫查找有沒有 a.jar,沒有就會去私服下載,私服沒有會從中央倉庫下載到私服,而後下載本地倉庫。apache

image-20200607151711515

依賴傳遞

maven-a.jar 依賴 maven-b.jarspringboot

maven-b.jar 依賴 maven-c.jar微信

maven-client 項目中引入 maven-a.jar,那麼 maven-b.jarmaven-c.jar 都會引入進來。app

image-20200607154728583

依賴傳遞遵循的兩個規則

最短路徑原則

有了依賴傳遞,但也存在一個問題。

maven-a.jar 依賴 maven-b.jar

maven-b.jar 依賴 maven-c.jar(2.0)

maven-a.jar 依賴 maven-c.jar(1.0)

maven-client 項目中引入 maven-a.jar

最終會採用哪一個 maven-c.jar

因此 maven 依賴傳遞的其中一個規則就是,最短路徑原則

a -> b ->c(2.0)

a -> c(1.0)

maven-client 項目最終使用 1.0 的 c 。

最早聲明原則

最短路徑原則存在一個問題,當最短路徑同樣的時候怎麼辦,最早聲明原則就是再最短路徑相同的時候聲效。

maven-client 項目中引入 maven-a.jarmaven-b.jar

maven-b.jar 只依賴 maven-c.jar(2.0)

maven-a.jar 只依賴 maven-c.jar(1.0)

如今依賴的最短路徑同樣

maven-client -> maven-a -> maven-c(1.0)

maven-client -> maven-b -> maven-c(2.0)

maven-client 先引入的 maven-a 那麼 maven-c 1.0 聲效

maven-client 先引入的 maven-b 那麼 maven-c 2.0 聲效

最早聲明有點達不到咱們的預期,我能夠能夠這樣解決。

  • 第一種,打破最短依賴路徑,直接在 maven-client 引入你想要的 maven-c 的版本。
<dependencies>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>maven-a</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>maven-b</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>maven-c</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>
複製代碼
  • 第二種,排除 jar

這樣排除掉 maven-b 傳遞過來的 maven-c。根據本身的需求

<dependencies>

    <dependency>
        <groupId>org.example</groupId>
        <artifactId>maven-a</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>maven-b</artifactId>
        <version>1.0-SNAPSHOT</version>
        <exclusions>
            <exclusion>
                <groupId>org.example</groupId>
                <artifactId>maven-c</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>
複製代碼

依賴做用域

依賴的做用域定義了 jar 在何時生效,打包成 war 或者 jar 的時候是否打包進去。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
複製代碼

scope 取值不一樣,意義不同。

compile

scope 默認取值 compile 標識,當前依賴包,參與項目的編譯、運行、測試、打包。

runtime

runtime 標識不參與項目編譯,參與項目的運行、測試、打包。

provided

provided 標識參與項目的編譯、運行、測試,可是不參與打包。

system

system 用於咱們開發的一些二方庫,可是不能發佈到網上,可使用這種場景去使用。默認這種 jar 不會打包進去,須要咱們配置一下。

參與項目的編譯、運行、測試。

<dependencies>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>maven-d.jar</artifactId>
        <version>1.0-SNAPSHOT</version>
        <scope>system</scope>
        <systemPath>${basedir}/lib/maven-d.jar</systemPath>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>${basedir}/lib</directory>
            <targetPath>BOOT-INF/lib/</targetPath>
            <includes>
                <include>**/*.jar</include>
            </includes>
        </resource>
    </resources>
</build>
複製代碼

test

test 標識只在編譯測試代碼和運行測試代碼的時候須要,別的都不用,打包的時候也不會包含。

import

通常咱們會在父工程使用這個做用域。表示從其它的 pom.xml 導入 dependency 的配置。

好比咱們本身的父工程,只想要 springboot 的依賴管理。

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
複製代碼

繼承和聚合

繼承

maven-client 繼承了 maven-demo

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <parent>
        <artifactId>maven-demo</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>
    <artifactId>maven-client</artifactId>
</project>
複製代碼

聚合

maven-demo 聚合了五個工程。

<?xml version="1.0" encoding="UTF-8"?>
<project >
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.example</groupId>
    <artifactId>maven-demo</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>maven-a</module>
        <module>maven-b</module>
        <module>maven-c</module>
        <module>maven-client</module>
        <module>maven-d</module>
    </modules>
</project>
複製代碼

繼承用於消除冗餘配置,好比一些配置打包配置,配置的變量,項目依賴和插件依賴版本管理

聚合用於快速構建項目。

聚合以前打包 a,b,c,d,clent 須要分別運行 mvn package。

聚合以後,我我們只須要在 maven-demo 下運行 mvn package。

生命週期

maven 內部有三個構建週期。clean ,default,site。

其中 default 是咱們常用的生命週期。

clean 生命週期

只幹一件事情,將編譯生成的東西刪除乾淨。

default 生命週期

默認生命週期大體由下面幾個階段組成。

resources -> compile -> testResources -> testCompile -> test -> package -> install -> deploy

介紹下咱們經常使用的。

resources:拷貝 src/main/resources 下資源到 classpath 下。

compile:編譯項目源碼

testResources:拷貝 src/test/resources 到 測試的 test 的 classpath 下

test:運行單元測試

package:打包

install:安裝 jar 到本地倉庫

deploy: 發佈 jar 到遠程倉庫或私有倉庫

image-20200607175812514

自定義操做到生命週期某個階段

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <descriptors>
            <descriptor>${basedir}/assembly/package.xml</descriptor>
        </descriptors>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>
複製代碼

不一樣的生命週期一塊兒運行。

mvn clean package

限制性 clean 生命週期,再執行 default 生命週期到 package 階段。

私服和鏡像的使用

配置鏡像

mirrorOf 指定代理那個倉庫 settings.xml配置鏡像

<localRepository>
    /Users/zhangpanqin/.m2/repository
</localRepository>
<mirrors>
    <mirror>
        <id>aliyunmaven</id>
        <!-- 被鏡像的中央倉庫 id -->
        <mirrorOf>central</mirrorOf>
        <name>中央倉庫鏡像</name>
        <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
</mirrors>
複製代碼

你也能夠在 pom.xml 配置私服

<repositories>
    <repository>
        <id>ali_maven</id>
        <url>https://maven.aliyun.com/repository/central/</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>
複製代碼

定義不一樣的配置環境

你也能夠根據不一樣的配置環境,啓動不一樣的 jdk 環境,或者根據不一樣的環境啓動不一樣的鏡像

settings.xml 配置。

<profiles>
    <profile>
        <id>test-1</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <repositories>
            <repository>
                <id>public-snapshots</id>
                <name>public-snapshots</name>
                <url>http://mvn.uinnova.cn/nexus/content/groups/public</url>
                <releases>
                    <enabled>true</enabled>
                    <!--該元素指定更新發生的頻率。Maven會比較本地POM和遠程POM的時間戳。這裏的選項是:always(一直),daily(默認,每日),interval:X(這裏X是以分鐘爲單位的時間間隔),或者never(從不)。 -->
                    <updatePolicy>daily</updatePolicy>
                    <!--當Maven驗證構件校驗文件失敗時該怎麼作-ignore(忽略),fail(失敗),或者warn(警告)。 -->
                    <checksumPolicy>warn</checksumPolicy>
                </releases>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </repository>
        </repositories>
    </profile>
</profiles>
複製代碼

也能夠針對具體的項目配置

<profiles>
    <!-- 定義配置環境 打包的環境 mvn clean package -Pdev -->
    <profile>
        <id>local</id>
        <properties>
            <profileActive>local</profileActive>
        </properties>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
    </profile>

    <profile>
        <id>dev</id>
        <properties>
            <profileActive>dev</profileActive>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <profileActive>prod</profileActive>
        </properties>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
    </profile>

    <profile>
        <id>test</id>
        <properties>
            <profileActive>test</profileActive>
        </properties>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
    </profile>
</profiles>
複製代碼

maven-assembly-plugin 打包

pom.xml 配置

<build>
    <finalName>flyyou</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <descriptors>
                    <descriptor>${basedir}/assembly/package.xml</descriptor>
                </descriptors>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
複製代碼

package.xml

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
    <!-- id 標識符,添加到生成文件名稱的後綴符。若是指定 id 的話,目標文件則是 ${artifactId}-${id}.tar.gz-->
    <id>${project.version}-${profileActive}-bin</id>
    <!-- 指定打的包是否包含打包層目錄(好比finalName是terminal-dispatch,當值爲true,全部文件被放在包內的terminal-dispatch目錄下,不然直接放在包的根目錄下)-->
    <!-- <includeBaseDirectory>true</includeBaseDirectory>-->
    <!-- 打包格式有zip、tar、tar.gz (or tgz)、tar.bz2 (or tbz2)、jar、dir、war,能夠同時指定多個打包格式-->
    <formats>
        <format>tar.gz</format>
        <format>zip</format>
    </formats>

    <fileSets>
        <!-- target 目錄下的 jar,打包進zip文件的 lib 目錄 -->

        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>lib</outputDirectory>
            <includes>
                <include>*.jar</include>
            </includes>
        </fileSet>
        <!-- 項目根目錄下的 bin 目錄打包進 zip bin -->
        <fileSet>
            <directory>${basedir}/bin</directory>
            <outputDirectory>bin</outputDirectory>
            <includes>
                <include>*.sh</include>
                <include>*.bat</include>
            </includes>
        </fileSet>
        <!-- 把項目根目錄下的 doc 目錄打包進 zip 中的 doc -->
        <fileSet>
            <directory>${basedir}/doc</directory>
            <outputDirectory>doc</outputDirectory>
            <includes>
                <include>pic/**</include>
                <include>*.md</include>
                <include>*.pdf</include>
            </includes>
        </fileSet>

        <!-- 把編譯路徑 classes 下的配置文件和日誌配置文件放到 zip 中的 conf -->
        <fileSet>
            <directory>${project.build.outputDirectory}</directory>
            <outputDirectory>conf</outputDirectory>
            <includes>
                <include>application-${profileActive}.yml</include>
                <include>logback-spring.xml</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>
複製代碼

打包以下圖

image-20200607182606397

配合 SpringBoot 使用

application.yml

spring:
 application:
 name: flyyou-service
 profiles:
 active:  @profileActive@
複製代碼

圖形化界面切換開發環境,不再用不停修改配置文件了

*-local.yml.gitignore 忽略掉,本地開發環境各個之間互不影響。

image-20200607182749440

自動構建的時候使用下面命令,打包開發環境

mvn clean package -Ddev


本文由 張攀欽的博客 www.mflyyou.cn/ 創做。 可自由轉載、引用,但需署名做者且註明文章出處。

如轉載至微信公衆號,請在文末添加做者公衆號二維碼。微信公衆號名稱:Mflyyou

相關文章
相關標籤/搜索