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!