maven的pom文件與打包詳解

setting.xml 是全局級別的配置文件,主要用於配置 maven 的運行環境等一系列通用的屬性。

pom.xml 是項目級別的配置文件 。 pom 作為項目對象模型。通過 xml 表示 maven 項目,使用 pom.xml 來實現。主要描述瞭:項目的 maven 坐標、依賴關系、開發者需要遵循的規則、缺陷管理系統、組織和 licenses、項目的 url、項目的依賴性,以及其他所有的項目相關因素。

一、基礎配置

<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.0http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  
    <!-- 模型版本。maven2.0必須是這樣寫,現在是maven2唯一支持的版本 -->  
    <modelVersion>4.0.0</modelVersion>  
  
    <!-- 公司或者組織的唯一標志,並且配置時生成的路徑也是由此生成, 如 cn.edu.ouc,maven 會將該項目打成的 jar 包放本地路徑:/cn/edu/ouc -->  
    <groupId>cn.edu.ouc</groupId>    
    <!-- 本項目的唯一ID,一個groupId下面可能多個項目,就是靠artifactId來區分的 -->  
    <artifactId>pom-learning</artifactId>    
    <!-- 本項目目前所處的版本號 -->  
    <version>1.0.0-SNAPSHOT</version>    
    <!-- 打包的機制,如 pom、jar、maven-plugin、ejb、war、ear、rar和par,默認為jar -->  
    <packaging>jar</packaging>  
  
  	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
    </parent>
    
    <!-- 幫助定義構件輸出的一些附屬構件,附屬構件與主構件對應,有時候需要加上classifier才能唯一的確定該構件 不能直接定義項目的classifer,因為附屬構件不是項目直接默認生成的,而是由附加的插件幫助生成的 -->  
    <classifier>...</classifier>  

    <!-- 為 pom 定義一些常量,在 pom 中的其它地方可以直接引用這些變量。使用方式如下:${file.encoding} -->  
    <properties>  
        <file.encoding>UTF-8</file.encoding>  
        <java.source.version>1.5</java.source.version>  
        <java.target.version>1.5</java.target.version>  
    </properties>  
  
    <!-- 定義本項目的依賴關系 -->  
    <dependencies>   
        <!-- 每個dependency都對應這一個jar包 -->  
        <dependency>    
            <!--一般情況下,maven是通過groupId、artifactId、version這三個元素值(俗稱坐標)來檢索該構件, 然後引入你的工程。如果別人想引用你現在開發的這個項目(前提是已開發完畢並發佈到瞭遠程倉庫),-->   
            <!--就需要在他的pom文件中新建一個dependency節點,將本項目的groupId、artifactId、version寫入, maven就會把你上傳的jar包下載到他的本地 -->  
            <groupId>org.springframework</groupId>
      		<artifactId>spring-webmvc</artifactId>
      		<version>5.1.5.RELEASE</version>    
            <!-- maven認為,程序對外部的依賴會隨著程序的所處階段和應用場景而變化,所以maven中的依賴關系有作用域(scope)的限制。 -->  
            <!--scope包含如下的取值:compile(編譯范圍)、provided(已提供范圍)、runtime(運行時范圍)、test(測試范圍)、system(系統范圍) -->  
            <scope>test</scope>    
            <!-- 設置子項目是否默認繼承該依賴:默認為 false,即子項目默認都繼承,子項目不需要顯示的引入;若為 true 則子項目必需顯示的引入,與dependencyManagement裡定義的依賴類似  -->  
            <optional>false</optional>    
            <!-- 屏蔽依賴關系,使其不起作用。比如項目中使用的libA依賴某個庫的1.0版,libB依賴某個庫的2.0版,現在想統一使用2.0版,就應該屏蔽掉對1.0版的依賴 -->  
            <exclusions>  
                <exclusion>  
                    <groupId>org.slf4j</groupId>  
                    <artifactId>slf4j-api</artifactId>  
                </exclusion>  
            </exclusions>    
        </dependency>    
    </dependencies>    
    ...  
</project>  

一般來說,上面的幾個配置項對任何項目都是必不可少的,定義瞭項目的基本屬性。

1、<parent> 標簽

< parent> 用於引用父工程,統一管理默認配置以及 jar 包的版本,其依賴需要在子工程中定義才有效。

1)使用 spring-boot-starter-parent

spring-boot-starter-parent 是一個特殊的 starter,它用來提供相關的 Maven 默認依賴:定義 Java 編譯版本為 1.8 ;項目使用 UTF-8 編碼;繼承自 spring-boot-dependencies,這個裡邊定義瞭依賴的版本,也正是因為繼承瞭這個依賴,所以我們在寫依賴時才不需要寫版本號;執行打包操作的配置;自動化的資源過濾;自動化的插件配置;針對 application.properties 和 application.yml 的資源過濾,包括通過 profile 定義的不同環境的配置文件。

2)使用自定義 parent

但是並非所有的公司都需要這個 parent,有的時候,公司會自定義 parent,我們的 SpringBoot 項目隻能繼承一個 parent,繼承瞭公司內部的 parent 就不能再繼承這個瞭,這個時候怎麼辦呢?

對於依賴版本,我們可以定義 <dependencyManagement> 節點,然後在裡面定義好版本號,接下來引用依賴時也就不用寫版本號瞭,像下面這樣:

<dependencyManagement> 		
	<dependencies> 			
		<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-starter-parent</artifactId>
				<version>2.3.1.RELEASE</version>
				<type>pom</type>
				<scope>import</scope> 			
		</dependency> 		
	</dependencies> 	
</dependencyManagement>

這樣寫之後,就可以不用繼承spring-boot-starter-parent瞭,但依賴的版本號問題雖然解決瞭,但是關於打包的插件、編譯的JDK版本、文件的編碼格式等等這些配置,在沒有parent的時候,這些統統要自己去配置。

Java版本的配置很簡單,添加一個plugin即可:

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

編碼格式,在pom.xml中加入如下配置:

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

2、classifier 元素

這裡有必要對一個不太常用的屬性 classifier 做一下解釋,因為有時候引用某個 jar 包,classifier 不寫的話會報錯。

classifier 元素用來幫助定義構件輸出的一些附屬構件。附屬構件與主構件對應,比如主構件是 kimi-app-2.0.0.jar,該項目可能還會通過使用一些插件生成,如 kimi-app-2.0.0-javadoc.jar (Java文檔)、kimi-app-2.0.0-sources.jar(Java源代碼)這樣兩個附屬構件。這時候javadoc、sources 就是這兩個附屬構件的 classifier,這樣附屬構件也就擁有瞭自己唯一的坐標。

3、classifier 的用途:

1)maven download javadoc / sources jar 包的時候,需要借助 classifier 指明要下載那個附屬構件
2)引入依賴的時候,有時候僅憑 groupId、artifactId、version 無法唯一的確定某個構件,需要借助 classifier 來進一步明確目標。比如 JSON-lib,有時候會同一個版本會提供多個jar包,在 JDK1.5 環境下是一套,在 JDK1.3 環境下是一套:

在這裡插入圖片描述

引用它的時候就要註明 JDK 版本,否則 maven 不知道你到底需要哪一套jar包:

<dependency>   	
	<groupId>net.sf.json-lib</groupId>  
	<artifactId>json-lib</artifactId>   	
	<version>2.4</version>  
	<classifier>jdk15</classifier>   
</dependency> 

二、構建配置

<build>  
  
    <!-- 產生的構建的文件名,默認值是 ${artifactId}-${version} -->  
    <finalName>myPorjectName</finalName>  
  
    <!-- 構建產生的所有文件存放的目錄,默認為 ${basedir}/target,即項目根目錄下的 target -->  
    <directory>${basedir}/target</directory>  
  
    <!--當項目沒有規定目標(Maven2叫做階段(phase))時的默認值 -->  
    <!--必須跟命令行上的參數相同例如jar:jar,或者與某個階段(phase)相同例如install、compile等 -->  
    <defaultGoal>install</defaultGoal>  
  
    <!--當 filtering 開關打開時,使用到的過濾器屬性文件列表。 -->  
    <!--項目配置信息中諸如 ${spring.version} 之類的占位符會被屬性文件中的實際值替換掉 -->  
    <filters>  
        <filter>../filter.properties</filter>  
    </filters>  
  
    <!--項目相關的所有資源路徑列表,例如和項目相關的配置文件、屬性文件,這些資源被包含在最終的打包文件裡。 -->  
    <resources>  
    
        <resource>    
            <!--描述瞭資源的目標路徑。該路徑相對target/classes目錄(例如${project.build.outputDirectory})。 -->  
            <!--舉個例子,如果你想資源在特定的包裡(org.apache.maven.messages),你就必須該元素設置為org/apache/maven/messages。 -->  
            <!--然而,如果你隻是想把資源放到源碼目錄結構裡,就不需要該配置。 -->  
            <targetPath>resources</targetPath>   
            <!--是否使用參數值代替參數名。參數值取自properties元素或者文件裡配置的屬性,文件在filters元素裡列出。 -->  
            <filtering>true</filtering>    
            <!--描述存放資源的目錄,該路徑相對POM路徑 -->  
            <directory>src/main/resources</directory>  
  
            <!--要被打包的資源列表 -->  
            <includes>  
                <include>**/*.properties</include>  
                <include>**/*.xml</include>  
            </includes>  
  
            <!--排除的資源列表,這些資源不會被打包。如果<include>與<exclude>劃定的范圍存在沖突,以<exclude>為準 -->  
            <excludes>  
                <exclude>jdbc.properties</exclude>  
            </excludes> 
               
        </resource>  
    </resources>  
  
    <!--單元測試需要用到的的所有資源路徑,配置方法與resources類似 -->  
    <testResources>  
        <testResource>  
            <targetPath />  
            <filtering />  
            <directory />  
            <includes />  
            <excludes />  
        </testResource>  
    </testResources>  
  
    <!--項目源碼目錄,當構建項目的時候,構建系統會編譯目錄裡的源碼。該路徑是相對於pom.xml的相對路徑。 -->  
    <sourceDirectory>${basedir}\src\main\java</sourceDirectory>  
  
    <!--項目腳本源碼目錄,該目錄和源碼目錄不同,絕大多數情況下,該目錄下的內容會被拷貝到輸出目錄(因為腳本是被解釋的,而不是被編譯的)。 -->  
    <scriptSourceDirectory>${basedir}\src\main\scripts  
    </scriptSourceDirectory>  
  
    <!--項目單元測試使用的源碼目錄,當測試項目的時候,構建系統會編譯目錄裡的源碼。該路徑是相對於pom.xml的相對路徑。 -->  
    <testSourceDirectory>${basedir}\src\test\java</testSourceDirectory>  
  
    <!--被編譯過的應用程序class文件存放的目錄。 -->  
    <outputDirectory>${basedir}\target\classes</outputDirectory>  
  
    <!--被編譯過的測試class文件存放的目錄。 -->  
    <testOutputDirectory>${basedir}\target\test-classes</testOutputDirectory>  
  
    <!--項目的一系列構建擴展,它們是一系列build過程中要使用的產品,會包含在running bulid's classpath裡面。 -->  
    <!--他們可以開啟extensions,也可以通過提供條件來激活plugins。 -->  
    <!--簡單來講,extensions是在build過程被激活的產品 -->  
    <extensions>  
  
        <!--例如,通常情況下,程序開發完成後部署到線上Linux服務器,可能需要經歷打包、將包文件傳到服務器、SSH連上服務器、敲命令啟動程序等一系列繁瑣的步驟。 -->  
        <!--實際上這些步驟都可以通過Maven的一個插件 wagon-maven-plugin 來自動完成 -->  
        <!--下面的擴展插件wagon-ssh用於通過SSH的方式連接遠程服務器, -->  
        <!--類似的還有支持ftp方式的wagon-ftp插件 -->  
        <extension>  
            <groupId>org.apache.maven.wagon</groupId>  
            <artifactId>wagon-ssh</artifactId>  
            <version>2.8</version>  
        </extension>  
  
    </extensions>  
  
    <!--使用的插件列表 。 -->  
    <plugins>  
        <plugin>  
            <groupId></groupId>  
            <artifactId>maven-assembly-plugin</artifactId>  
            <version>2.5.5</version>  
  
            <!--在構建生命周期中執行一組目標的配置。每個目標可能有不同的配置。 -->  
            <executions>  
                <execution>  
  
                    <!--執行目標的標識符,用於標識構建過程中的目標,或者匹配繼承過程中需要合並的執行目標 -->  
                    <id>assembly</id>  
  
                    <!--綁定瞭目標的構建生命周期階段,如果省略,目標會被綁定到源數據裡配置的默認階段 -->  
                    <phase>package</phase>  
  
                    <!--配置的執行目標 -->  
                    <goals>  
                        <goal>single</goal>  
                    </goals>  
  
                    <!--配置是否被傳播到子POM -->  
                    <inherited>false</inherited>  
  
                </execution>  
            </executions>  
  
            <!--作為DOM對象的配置,配置項因插件而異 -->  
            <configuration>  
                <finalName>${finalName}</finalName>  
                <appendAssemblyId>false</appendAssemblyId>  
                <descriptor>assembly.xml</descriptor>  
            </configuration>  
  
            <!--是否從該插件下載Maven擴展(例如打包和類型處理器), -->  
            <!--由於性能原因,隻有在真需要下載時,該元素才被設置成true。 -->  
            <extensions>false</extensions>  
  
            <!--項目引入插件所需要的額外依賴 -->  
            <dependencies>  
                <dependency>...</dependency>  
            </dependencies>  
  
            <!--任何配置是否被傳播到子項目 -->  
            <inherited>true</inherited>  
  
        </plugin>  
    </plugins>  
  
    <!--主要定義插件的共同元素、擴展元素集合,類似於dependencyManagement, -->  
    <!--所有繼承於此項目的子項目都能使用。該插件配置項直到被引用時才會被解析或綁定到生命周期。 -->  
    <!--給定插件的任何本地配置都會覆蓋這裡的配置 -->  
    <pluginManagement>  
        <plugins>...</plugins>  
    </pluginManagement>  
  
</build>

Maven 是通過 pom.xml 來執行任務的,其中的 <build> 標簽描述瞭如何來編譯及打包項目,而具體的編譯和打包工作是通過 build 中配置的 plugin 來完成。當然plugin配置不是必須的,默認情況下,Maven 會綁定以下幾個插件來完成基本操作。

在這裡插入圖片描述

在 Maven的pom.xml 文件中,存在如下兩種 <build>:

全局配置(project build):是<project>的直接子元素,針對整個項目的所有情況都有效;
局部配置(profile build):是<profile>的直接子元素,針對不同的profile配置。

字段說明

1、finalName:build目標文件的名稱,默認情況為 ${artifactId}-${version}。
2、defaultGoal:執行 build 任務時,如果沒有指定目標,將使用的默認值。如上配置,在命令行中執行 mvn,則相當於執行 mvn install。
3、directory:build 結果文件的存放目錄,默認在 ${basedir}/target 目錄。
4、filter:定義 *.properties 文件,包含一個 properties 列表,該列表會應用到支持 filter 的 resources 中。也就是說,定義在 filter 的文件中的 name=value 鍵值對,會在 build 時代替 ${name}
值應用到 resources 中。maven 的默認 filter 文件夾為 ${basedir}/src/main/filters。
5、resources: 一個 resource 元素的列表。每一個都描述與項目關聯的文件是什麼和在哪裡。
6、testResources: 定義和resource類似,隻不過在test時使用。
7、Project Build 特有的 <…Directory>:往往配置在父項目中,供所有父子項目使用。

在這裡插入圖片描述

8、Project Build 特有的 <extensions>:<extensions> 是執行構建過程中可能用到的其他工具,在執行構建的過程中被加入到 classpath 中。也可以通過 <extensions>**構建插件,從而改變構建的過程。通常,通過 <extensions> 給出通用插件的一個具體實現,用於構建過程。

在這裡插入圖片描述

9、plugins:<plugins> 給出構建過程中所用到的插件。

在這裡插入圖片描述

  • groupId
  • artifactId
  • version
  • extensions:是否加載該插件的擴展,默認false;
  • inherited:該插件的 configuration 中的配置是否可以被(繼承該POM的其他Maven項目)繼承,默認true;
  • configuration:該插件所需要的特殊配置,在父子項目之間可以覆蓋或合並;
  • dependencies:該插件所特有的依賴類庫;
  • executions:該插件的某個goal(一個插件中可能包含多個goal)的執行方式。一個execution有如下設置:
    • id:唯一標識;
    • goals:要執行的插件的goal(可以有多個),如<goal>run</goal>;
    • phase:插件的goal要嵌入到Maven的phase中執行,如verify;
    • inherited:該execution是否可被子項目繼承;
    • configuration:該execution的其他配置參數;

10、<pluginManagement> :在 <build> 中,<pluginManagement> 與 <plugins> 並列,兩者之間的關系類似於 <dependencyManagement> 與 <dependencies> 之間的關系。<pluginManagement> 中也配置 <plugin>,其配置參數與 <plugins> 中的 <plugin>完全一致。<pluginManagement> 往往出現在父項目中,其中配置的 <plugin>往往通用於子項目。子項目中隻要在 <plugins> 中以 <plugin> 聲明該插件,該插件的具體配置參數則繼承自父項目中 <pluginManagement> 對該插件的配置,從而避免在子項目中進行重復配置

三、profile 配置

有些時候,一個項目需要適配多種開發環境,如數據庫不同(mysql、oracle、db2等)、如開發環境不同(dev、pro、test)等不同的環境需要指定不同的配置。這種情況下,我們就可以采用配置 profiles 來控制。在啟動的時候指定不同的配置組合,maven進行build時會自動選擇指定配置。

    <!--  定義配置文件  -->
    <profiles>
        <!--  配置文件  id 名字    properties 參數   -->
        <profile>
            <id>dev</id>            
            <!--自動觸發profile的條件邏輯。Activation是profile的開啟鑰匙。 -->  
            <activation>
            	 <!--profile默認是否激活的標識 -->  
                <activeByDefault>true</activeByDefault>
                <!--activation有一個內建的java版本檢測,如果檢測到jdk版本與期待的一樣,profile被激活。 -->  
            	<jdk>1.7</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中通過${名稱}引用),其擁有對應的名稱和值,Profile就會被激活。 -->  
            	<!-- 如果值字段是空的,那麼存在屬性名稱字段就會激活profile,否則按區分大小寫方式匹配屬性值字段 -->  
            	<property>    
                	<!--激活profile的屬性的名稱 -->  
                	<name>profileProperty</name>    
                	<!--激活profile的屬性的值 -->  
                	<value>dev</value>    
            	</property>    
            	<!--提供一個文件名,通過檢測該文件的存在或不存在來激活profile。missing檢查文件是否存在,如果不存在則激活profile。 -->  
            	<!--另一方面,exists則會檢查文件是否存在,如果存在則激活profile。 -->  
            	<file>  
                	<!--如果指定的文件存在,則激活profile。 -->  
                	<exists>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/</exists>  
                	<!--如果指定的文件不存在,則激活profile。 -->  
                	<missing>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/</missing>    
            	</file>    
            </activation>
            <properties>
            	<!-- 該 profile 的映射路徑 -->
                <profiles.active>dev</profiles.active>
                <!--  眾多參數配置 -->
                <db.driver>com.mysql.jdbc.Driver</db.driver>
            	<db.url>jdbc:mysql://localhost:3306/test</db.url>
            	<db.username>root</db.username>
            	<db.password>root</db.password>
            </properties>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-quartz</artifactId>
                </dependency>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.1.43</version>
                </dependency>
            </dependencies>
            <!-- 打包配置 build -->
            <build>        
        		<resources>
            		<!-- 配置一個 resource -->
            		<resource>
            			<!-- 資源文件所在的路徑 -->
                		<directory>src/main/resources/</directory>
                		<!-- 打包自動忽略以下資源文件,不會被打包進來 -->
                		<excludes>
                    		<exclude>config/dev/*</exclude>
                    		<exclude>config/pro/*</exclude>
                    		<exclude>config/test/*</exclude>
                		</excludes>
                		<!-- 包含進來,防止打包時忽略掉除環境配置文件以外的對象 -->
                		<includes>
                    		<include>views/*</include>
                		</includes>
            		</resource>            		
            		<resource>
                		<!--這裡是關鍵! 根據不同的環境,把對應文件夾裡的配置文件打包-->
                		<directory>src/main/resources/config/${profiles.active}</directory>
            		</resource>
        		</resources>
    		</build>
        </profile>
        
        <profile>
            <id>pro</id>
            <properties>
                <profiles.active>pro</profiles.active>
                <!--  眾多參數配置 -->
            </properties>
        </profile>
        
        <profile>
            <id>test</id>
            <properties>
                <profiles.active>test</profiles.active>
                <!--  眾多參數配置 -->
            </properties>
        </profile>
    </profiles>

 	 <!-- 全局 build -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

四、springboot 打包配置

SpringBoot 自帶Tomcat,所以我們的項目可以單獨部署,不需要依賴 Window、Linux 系統中的服務器,所以打包出來的 Jar 包是可以直接運行的

打包插件

SpringBoot 項目可以通過 maven 的插件進行打包,分為兩種情況:

(1)項目以 spring-boot-starter-parent 作為 parent

<plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

(2)項目不以 spring-boot-starter-parent 作為 parent

有時項目的 parent 不是 spring-boot-starter-parent,而是自定義的配置,此時 spring-boot-maven-plugin 插件不能直接使用,需要做一些修改。

<plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <version>2.0.4.RELEASE</version>
      <configuration>
     	 <!--  打包出來的jar/war就是可執行的 -->      	
      	<executable>true</executable>
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>repackage</goal>
          </goals>
        </execution>
      </executions> 
</plugin> 

經過這樣配置,就可以進行打包瞭。

1、Maven 項目結構

Maven 項目的標準目錄結構:

在這裡插入圖片描述

構建 Maven 項目的時候,如果沒有進行特殊的配置,Maven 會按照標準的目錄結構查找和處理各種類型文件。

(1) src/main/java 和 src/test/java 這兩個目錄中的所有 *.java 文件會分別在 compile 和 test-comiple 階段被編譯,編譯結果分別放到瞭 target/classes 和 targe/test-classes 目錄中,但是這兩個目錄中的其他文件都會被忽略掉
(2) src/main/resouces 和 src/test/resources 這兩個目錄中的文件也會分別被復制到 target/classes 和target/test-classes 目錄中

在這裡插入圖片描述

在 springboot 項目中,打包插件默認會把這個目錄中的所有內容打入到 jar 包或者 war 包中,然後放在 BOOT-INF 目錄下。

在這裡插入圖片描述

2、打包時資源文件的配置

(1)打包 src/main/java 目錄下的 xml

一般情況下,我們用到的資源文件(各種xml,properites,xsd文件等)都放在src/main/resources下面,利用 maven 打包時,maven 能把這些資源文件打包到相應的 jar 或者 war 裡。

有時候,比如 mybatis 的 mapper.xml 文件,我們習慣把它和 Mapper.java 放一起,都在 src/main/java 下面,這樣利用 maven 打包時,就需要修改 pom.xml 文件,來把 mapper.xml 文件一起打包進 jar 或者 war 裡瞭,否則,這些文件不會被打包的。(maven認為src/main/java隻是java的源代碼路徑)

例如:

在這裡插入圖片描述

默認情況下,執行 mvn clean package 打包命令後在 target\classes 目錄下不會把 UserMapper.xml 打包到下 mapper 目錄下。

在這裡插入圖片描述

解決方法有如下幾種:

1)配置 POM.XML 的 resource 把 xml 也打包到 mapper 目錄下

    <build>
       <!-- 資源目錄 -->    
        <resources>    
            <resource>    
                <!-- 設定主資源目錄  -->    
                <directory>src/main/java</directory>    
 
                <!-- maven default生命周期,process-resources階段執行maven-resources-plugin插件的resources目標處理主資源目下的資源文件時,隻處理如下配置中包含的資源類型
-->     
				 <includes>
					  <include>**/*.xml</include>
				 </includes>  
                     
                <!-- maven default生命周期,process-resources階段執行maven-resources-plugin插件的resources目標處理主資源目下的資源文件時,不處理如下配置中包含的資源類型(剔除下如下配置中包含的資源類型)-->      
				<excludes>  
					<exclude>**/*.yaml</exclude>  
				</excludes>  
 
                <!-- maven default生命周期,process-resources階段執行maven-resources-plugin插件的resources目標處理主資源目下的資源文件時,指定處理後的資源文件輸出目錄,默認是${build.outputDirectory}指定的目錄-->

                <!--<targetPath>${build.outputDirectory}</targetPath> -->      
   
                <!-- maven default生命周期,process-resources階段執行maven-resources-plugin插件的resources目標處理主資源目下的資源文件時,是否對主資源目錄開啟資源過濾
-->    
                <filtering>true</filtering>     
            </resource>  			
        </resources> 	   
    </build> 

2)maven-resources-plugin 插件

為瞭使項目結構更為清晰,Maven區別對待Java代碼文件和資源文件,maven-compiler-plugin用來編譯Java代碼,maven-resources-plugin則用來處理資源文件。
默認的主資源文件目錄是src/main/resources,很多用戶會需要添加額外的資源文件目錄,這個時候就可以通過配置maven-resources-plugin來實現。

            <!-- 利用此plugin,把源代碼中的xml文件,打包到相應位置,這裡主要是為瞭打包Mybatis的mapper.xml文件-->
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.5</version>
                <executions>
                    <execution>
                        <id>copy-xmls</id>
                        <phase>process-sources</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${basedir}/target/classes</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>${basedir}/src/main/java</directory>
                                    <includes>
                                        <include>**/*.xml</include>
                                    </includes>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin> 

3)build-helper-maven-plugin 插件

<!-- 利用此plugin,把源代碼中的xml文件,打包到相應位置,這裡主要是為瞭打包Mybatis的mapper.xml文件  -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.8</version>
                <executions>
                    <execution>
                        <id>add-resource</id>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>add-resource</goal>
                        </goals>
                        <configuration>
                            <resources>
                                <resource>
                                    <directory>src/main/java</directory>
                                    <includes>
                                        <include>**/*.xml</include>
                                    </includes>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin> 

(2)src/main/resources 目錄下的 xml 等資源文件不被打包

默認 resources 目錄下的文件都會被打包,如果想 resources 目錄下的 xml 文件不被打包,可通過如下配置:

	<!--過濾resource下的文件-->
	<resources>  
        <resource>  
            <directory>src/main/resources</directory>  
            <includes>  
                <include>*.properties</include>  <!--打包properties文件-->
            </includes>  
            <excludes>  
                <exclude>*.xml</exclude>  <!--過濾xml與yaml文件-->
                <exclude>*.yaml</exclude>  
            </excludes>  
        </resource>  
    </resources>

當然也可以通過插件來實現:

    <plugin>  
        <artifactId>maven-resources-plugin</artifactId>  
        <executions>  
            <execution>  
                <id>copy-resources</id>  
                <phase>validate</phase>  
                <goals>  
                    <goal>copy-resources</goal>  
                </goals>  
                <configuration>  
 
					<!-- 並把文件復制到target/conf目錄下-->
                    <outputDirectory>${project.build.directory}/conf</outputDirectory>  
                    <resources>  
                        <resource>  
                            <directory>src/main/resources</directory>  
							<!-- 指定不需要處理的資源 <excludes> <exclude>WEB-INF/*.*</exclude> </excludes> -->  
							<excludes> 
								<exclude>**/*.xml</exclude> 
							</excludes>
                            <filtering>true</filtering>  
                        </resource>  
                    </resources>  
                </configuration>  
            </execution>  
        </executions>  
    </plugin> 

實現的效果如下:

在這裡插入圖片描述

編譯好之後,會在target目錄下生成 conf 目錄並且把 resources 目錄下的所有文件都自動拷貝到 target/conf/ 目錄下。

四、倉庫配置

五、發佈配置

六、pom 項目依賴、繼承與聚合

1、項目之間的相互依賴

現在有兩個項目,HelloWorld1 和 HelloWorld2,如果 HelloWorld1 要引用 HelloWorld2 中的方法,也就是 HelloWorld1 要依賴 HelloWorld2。做法如下:

(1)在 helloworld1 項目之中,執行打包命令將當前項目打包成可依賴的 jar 包,並放進本地倉庫當中;
(2)在helloworld2 項目的 pom.xml 之中,加入 helloworld1 依賴。helloworld 的 jar 包坐標:

<dependency> 	
	<groupId>cn.edu.ouc</groupId>
	<artifactId>HelloWorld</artifactId> 	
	<version>1.0-SNAPSHOT</version>
</dependency> 

(3)通過 import 導入 jar 包,就成功的引入我們自定義的項目 jar 包。這樣就可以使用
helloworld1 項目的所有方法。

如何打包成可依賴的 jar 包

在 SpringBoot 工程中使用 spring-boot-maven-plugin 的默認配置 build,那麼所生成的 jar 包雖然是可執行的,但卻是不可被依賴的
通過修改 pom.xml 中 spring-boot-maven-plugin 的配置,可以讓所在工程一次打包生成兩個 jar 包,其中 XXX.jar 可作為其它工程的依賴,XXX-exec.jar 可被執行。

<plugin> 	
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
	<version>2.0.4.RELEASE</version> 	
	<executions>
    	<execution>
    		<goals>
    			<!--可以把依賴的包都打包到生成的Jar包中 -->
    			<goal>repackage</goal>
    		</goals>
    	</execution>
    </executions>
    <!--生成可執行 Jar 包 -->
    <configuration>
    	<classifier>exec</classifier>
    </configuration> 
</plugin> 

classifier 指定瞭可執行 jar 包的名字,默認的 jar 包則作為可被其他程序依賴的 Artifact。配置完成後對項目進行打包,會生成以下兩個 jar 包。

在這裡插入圖片描述

SpringbootDemo-1.0-SNAPSHOT.jar 是一個可以被其他項目依賴的 jar,
SpringbootDemo-1.0-SNAPSHOT-exec.jar 是一個可執行的 jar。
對其分別解壓,可以看到 class 路徑是不同的:

在這裡插入圖片描述

2、maven 父子項目依賴的繼承

現在有兩個項目 A 和 B,繼承就是說 B 項目之中依賴的包 A 項目也可以使用。一般用於統一管理依賴版本號

具體實現如下:

(1)創建父工程 parent,打包方式為 pom,並在其中依賴 junit.jar,註意要將依賴寫在 <dependencyManagement> 標簽之中

Maven 提供瞭 <dependencyManagement> 元素既能讓子模塊繼承到父模塊的依賴配置,又能保證子模塊依賴的使用靈活性。
在 <dependencyManagement> 標簽下的依賴聲明不會將依賴直接引入到父工程和子工程中,不過它能約束 dependencies 下的依賴配置;子模塊中隻有在<dependenices> 標簽中聲明的依賴才會被繼承並引入到子工程中

如下:

在這裡插入圖片描述

(2)在子工程 Helloworld 的 pom.xml 當中添加父工程標簽,這裡的 <relativePath> 是父工程的 pom.xml 文件的位置,其他是父工程的 gav。如下:

 <parent> 	
 	<groupId>org.apache.maven</groupId>
	<artifactId>parent</artifactId> 	
	<version>1.0-SNAPSHOT</version>
	<relativePath>../parent/pom.xml</relativePath> 
</parent> 

(3)在子工程當中,聲明需要使用父類當中的哪些 jar 包,聲明寫在 pom.xml 的 <dependenices> 標簽之中,子模塊不需要配置 jar 包的版本和作用域,隻需配置 groupId 和 artifactId。如下:

在這裡插入圖片描述

可以看到有一個向上繼承的符號,說明繼承已經成功瞭。更新之後發現 junit 已經導入。

3、多模塊項目的聚合

如果一個項目有多個模塊,也叫做多重模塊,或者合成項目。
如果不用聚合那麼每次打包每個模塊都要運行,但是用來聚合後,隻運行一次就行瞭。

<project>  
  <modelVersion>4.0.0<modelVersion>  
  <groupId>cn.edu.ouc<groupId>  
  <artifactId>my-parent<artifactId>  
  <version>2.0<version>  
  <modules>    	
  	<!-- 模塊相對於pom文件的位置-->
    <module>my-project1<module>  
    <module>my-project2<module>  
  <modules>  
<project>  

如果多個模塊有相同的內容,那麼就可以用一個父模塊來實現相同的內容,其他模塊隻要繼承父模塊就行瞭
父模塊中把所有 jar 包都引用進來,子模塊就不用配置 jar 包的版本和作用域瞭。(繼承)

反應堆:

在一個多模塊的 Maven 項目中,反應堆是指所有模塊組成的一個構建結構。反應堆包含瞭各個模塊之間的繼承與依賴關系,從而能夠自動計算出合理的模塊構建順序。

<modules>     
	<module>account-email</module>    
	<module>account-persist</module>     
	<module>account-parent</module>  
</modules>  

實際的構建順序為: ~parent, ~email, ~persist。可見構建的順序並不是聲明的順序。

該例中 account-email 和 account-persist 都依賴於 account-parent,那麼 account-parent 就必須在另外兩個模塊之前構建。
實際的構建順序是這樣的:Maven 按聲明順序讀取 POM,如果 POM 沒有依賴模塊,那麼就構建該模塊,否則就先構建其依賴的模塊;如果依賴的模塊還依賴於其他模塊,則進一步構建依賴的依賴

模塊之間的關系將反應堆構成一個有向非循環圖,各個模塊是該圖的節點,依賴關系構成又向邊,這個圖不允許出現循環,因此當出現 A 依賴於 B,B 又依賴於 A 的情況時 Maven 就會報錯

4、聚合與繼承的關系

在這裡插入圖片描述

(1)區別 :

1)對於聚合模塊來說,它知道有哪些被聚合的模塊,但那些被聚合的模塊不知道這個聚合模塊的存在。

2)對於繼承關系的父 POM 來說,它不知道有哪些子模塊繼承與它,但那些子模塊都必須知道自己的父 POM是什麼。

(2)共同點 :

1)聚合 POM 與繼承關系中的父 POM 的 packaging 都是 pom

2)聚合模塊與繼承關系中的父模塊除瞭 POM 之外都沒有實際的內容

現有的實際項目往往是一個POM既是聚合POM又是父POM,這麼做主要是為瞭方便。

到此這篇關於maven的pom文件與打包詳解的文章就介紹到這瞭,更多相關maven pom文件與打包內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: