1. Maven 依赖管理

    在开发中子模块可以通过继承获得父模块中声明的全部依赖,这样虽然避免了在各个子模块 POM 中重复进行依赖声明,但也极有可能造成子模块中引入一些不必要的依赖。为此 Maven 引入了 dependencyManagement 来对依赖进行管理。

    本文将在 “Maven基础知识(6)- Maven 依赖传递、POM 继承、Maven 聚合” 里 MavenDemo04 项目基础上,修改配置来演示相关功能的实现(下同)。

    1) 依赖管理

        Maven 可以通过 dependencyManagement 元素对依赖进行管理,它具有以下 2 大特性:

            (1) 在该元素下声明的依赖不会实际引入到模块中,只有在 dependencies 元素下同样声明了该依赖,才会引入到模块中;
            (2) 该元素能够约束 dependencies 下依赖的使用,即 dependencies 声明的依赖若未指定版本,则使用 dependencyManagement 中指定的版本,否则将覆盖 dependencyManagement 中的版本。

        示例,子模块 CoreLib 的 pom.xml 配置如下:

复制代码

 1             <project xmlns="http://maven.apache.org/POM/4.0.0" 2                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3                     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 4                                         https://maven.apache.org/xsd/maven-4.0.0.xsd"> 5  6                 <modelVersion>4.0.0</modelVersion> 7                 <groupId>com.example</groupId> 8                 <artifactId>CoreLib</artifactId> 9                 <version>1.0</version>10 11                 <!-- dependencyManagement 标签用于控制子模块的依赖版本等信息 -->12                 <!-- 该标签只用来控制版本,不能将依赖引入 -->13                 <dependencyManagement>14                     <dependencies>15                         <dependency>16                             <groupId>junit</groupId>17                             <artifactId>junit</artifactId>18                             <version>3.8.1</version>19                             <!-- <scope>test</scope> -->20                         </dependency>21                     </dependencies>22                 </dependencyManagement>23 24                 <!-- 声明依赖 -->25                 <dependencies>26                     <dependency>27                         <groupId>junit</groupId>28                         <artifactId>junit</artifactId>29                     </dependency>30                 </dependencies>31             </project>

复制代码

        在以上配置中,由于 dependencyManagement 元素中已经定义完整的依赖声明,所以在 dependencies 元素中声明的依赖只配置了 groupId 和 artifactId,省略了 version 和 scope。

        在实际的开发过程中,dependencyManagement 很少会单独使用,通常它需要与 Maven 继承或依赖范围 import 配合使用才能展现它的优势。

    2) 继承依赖管理

        由于 dependencyManagement 元素是可以被继承的,因此我们可以在父模块 POM 中使用 dependencyManagement 元素声明所有子模块的依赖,然后在各个子模块 POM 使用 dependencies 元素声明实际用到的依赖即可。这样既可以让子模块能够继承父模块的依赖配置,还能避免将不必要的依赖引入到子模块中。

        (1) 修改父模块 MavenDemo04 的 pom.xml 如下。

复制代码

 1             <project xmlns="http://maven.apache.org/POM/4.0.0" 2                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3                     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 4                                         https://maven.apache.org/xsd/maven-4.0.0.xsd"> 5  6                 <modelVersion>4.0.0</modelVersion> 7                 <groupId>com.example</groupId> 8                 <artifactId>MavenDemo04</artifactId> 9                 <version>1.0</version>10                 <packaging>pom</packaging>11                 <properties>12                     <!-- 定义 Maven 变量 -->13                     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>14                     <log4j.version>1.2.17</log4j.version>15                     <junit.version>3.8.1</junit.version>16                     <system.version>1.0</system.version>17                     <mariadb.client.version>2.7.4</mariadb.client.version>18                 </properties>19 20                 <dependencyManagement>21                     <dependencies>22                         <dependency>23                             <groupId>log4j</groupId>24                             <artifactId>log4j</artifactId>25                             <!-- 引用的 properties 标签中定义的变量 -->26                             <version>${log4j.version}</version>27                         </dependency>28                         <dependency>29                             <groupId>junit</groupId>30                             <artifactId>junit</artifactId>31                             <!--引用的 properties 标签中定义的变量 -->32                             <version>${junit.version}</version>33                             <!-- <scope>test</scope> -->34                         </dependency>35                         <dependency>36                             <groupId>org.mariadb.jdbc</groupId>37                             <artifactId>mariadb-java-client</artifactId>38                             <!--引用的 properties 标签中定义的变量 -->39                             <version>${mariadb.client.version}</version>40                             <scope>runtime</scope>41                         </dependency>42                     </dependencies>43                 </dependencyManagement>44             </project>

复制代码

            注:以上配置中,将所有依赖的版本信息以 Maven 变量(properties)的形式提取出来,这样不仅消除了一些重复,也使得各个依赖的版本信息更加明显,便于管理。

            在父模块 MavenDemo04 中使用 dependencyManagement 元素声明的依赖,既不会给 MavenDemo04 模块引入依赖,也不会给其子模块引入依赖,但这段配置是可以被继承的。

        (2) 修改子模块 CoreLib 的 pom.xml 如下。

复制代码

 1             <project xmlns="http://maven.apache.org/POM/4.0.0" 2                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3                     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 4                                         https://maven.apache.org/xsd/maven-4.0.0.xsd"> 5  6                 <modelVersion>4.0.0</modelVersion> 7                 <artifactId>CoreLib</artifactId> 8                 <parent> 9                     <groupId>com.example</groupId>10                     <artifactId>MavenDemo04</artifactId>11                     <version>1.0</version>12                     <!-- <relativePath>../MavenDemo04</relativePath> -->13                 </parent>                14                 <dependencies>15                     <dependency>16                         <groupId>log4j</groupId>17                         <artifactId>log4j</artifactId>18                     </dependency>19                     <dependency>20                         <groupId>junit</groupId>21                         <artifactId>junit</artifactId>22                     </dependency>23                     <dependency>24                         <groupId>org.mariadb.jdbc</groupId>25                         <artifactId>mariadb-java-client</artifactId>26                     </dependency>27                 </dependencies>28             </project>

复制代码

        在子模块 CoreLib 的 POM 中,所有在 dependencies 元素中声明的依赖都只配置了 groupId 和 artifactId,省去了 version 和 scope。之所以能够省略这些信息,是因为它们继承了父模块 MavenDemo04 中 dependencyManagement 的配置,其完整的依赖声明已经包含在父模块的 POM 中,子模块只需要配置 groupId 和 artifactId 就能获得相应的依赖信息,从而引入正确的依赖。

        使用这种依赖管理机制似乎并不能减少太多 POM 配置,但仍然推荐使用这种方式,其原因主要有 2 个:
        
            a) 在父模块中使用 dependencyManagement 声明依赖能够统一项目内依赖的版本,子模块无须声明版本,也就不会出现多个子模块使用同一依赖项版本不一致的情况,降低依赖冲突的几率;
            b) dependencyManagement 声明的依赖不会被实际引入,子模块需要什么依赖就自己引入,增加了灵活性,避免引入一些不必要的依赖。

    3) 导入依赖管理

        在 Maven 依赖传递 一节介绍依赖范围时,提到了一个名为 import 的依赖范围,之所以要放在这介绍是因为 import 依赖范围只能与 dependencyManagement 元素配合使用才会有效,其功能是将目标 pom.xml 中的 dependencyManagement 配置导入合并到当前 pom.xml 的 dependencyManagement 中。     

        例如,DataLib 模块想要使用 MavenDemo04 模块中的 dependencyManagement 配置,除了通过继承或者直接复制这两种方式之外,还可以使用 import 依赖范围将其导入,具体配置如下。

复制代码

 1             <project xmlns="http://maven.apache.org/POM/4.0.0" 2                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3                     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 4                                         https://maven.apache.org/xsd/maven-4.0.0.xsd"> 5  6                 <modelVersion>4.0.0</modelVersion> 7                 <groupId>com.example</groupId> 8                 <artifactId>DataLib</artifactId> 9                 <version>1.0</version>10                 <dependencyManagement>11                     <dependencies>12                         <!-- 导入依赖管理配置 -->13                         <dependency>14                             <groupId>com.example</groupId>15                             <artifactId>MavenDemo04</artifactId>16                             <version>1.0</version>17                             <!-- 依赖范围为 import -->18                             <scope>import</scope>19                             <!-- 类型一般为 pom -->20                             <type>pom</type>21                         </dependency>22                     </dependencies>23                 </dependencyManagement>24                 <!-- 声明依赖 -->25                 <dependencies>26                     <dependency>27                         <groupId>junit</groupId>28                         <artifactId>junit</artifactId>29                     </dependency>30                 </dependencies>31             </project>

复制代码

        以上配置中,由于 import 依赖范围的特殊性,一般都是指向打包类型为 pom 的模块,所以 type 元素的值一般为 pom。

        若存在多个模块,它们使用的依赖版本都是一致的,则就可以定义一个使用 dependencyManagement 专门管理依赖的 POM,然后在各个模块中导入这些依赖管理配置。

2. Maven 插件管理

    Maven 使用 dependencyManagement 对依赖进行管理,与之类似地,Maven 中还提供了一个名为 pluginManagement 的元素,它可以帮助用户管理 Maven 插件。

    1) 插件管理

        pluginManagement 元素与 dependencyManagement 元素的原理十分相似,在 pluginManagement 元素中可以声明插件及插件配置,但不会发生实际的插件调用行为,只有在 POM 中配置了真正的 plugin 元素,且其 groupId 和 artifactId 与 pluginManagement 元素中配置的插件匹配时,pluginManagement 元素的配置才会影响到实际的插件行为。

        例如,在 DataLib 模块中使用 pluginManagement 元素管理 maven-source-plugin 插件,并将其插件目标 jar-no-fork 绑定到 default 生命周期的 verify 阶段上,具体配置如下。

复制代码

 1             <project xmlns="http://maven.apache.org/POM/4.0.0" 2                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3                     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 4                                         https://maven.apache.org/xsd/maven-4.0.0.xsd"> 5  6                 <modelVersion>4.0.0</modelVersion> 7                 <artifactId>DataLib</artifactId> 8                 <parent> 9                     <groupId>com.example</groupId>10                     <artifactId>MavenDemo04</artifactId>11                     <version>1.0</version>12                 </parent>13                 <dependencies>14                     <dependency>15                         <groupId>junit</groupId>16                         <artifactId>junit</artifactId>17                     </dependency>18                 </dependencies>               19                 <build>20                     <!-- 添加插件管理 -->21                     <pluginManagement>22                         <plugins>23                             <!-- 声明插件 -->24                             <plugin>25                                 <groupId>org.apache.maven.plugins</groupId>26                                 <artifactId>maven-source-plugin</artifactId>27                                 <version>3.2.1</version>28                                 <executions>29                                     <!-- 将 jar-no-fork 目标绑定到 verify 阶段 -->30                                     <execution>31                                         <id>com.example</id>32                                         <phase>verify</phase>33                                         <goals>34                                             <goal>jar-no-fork</goal>35                                         </goals>36                                     </execution>37                                 </executions>38                             </plugin>39                         </plugins>40                     </pluginManagement>41                 </build>42             </project>

复制代码

        根据以上配置可以看出,使用 pluginManagement 管理插件很简单,只需要将声明插件的配置添加在 pluginManagement 元素中即可。

        由于该插件目标是绑定在 verify 阶段上,因此我们只需要执行 verify 或以后的阶段(如 install )即可调用 maven-source-plugin:jar-no-fork 目标。

        打开 cmd 命令行窗口,进入 D:\Workshop\maven\MavenDemo04\DataLib 目录,执行以下命令:

            D:\Workshop\maven\MavenDemo04\DataLib>mvn clean install

        显示结果如下:

复制代码

            [INFO] Scanning for projects...
            [INFO]
            [INFO] ------------------------< com.example:DataLib >-------------------------
            [INFO] Building DataLib 1.0
            [INFO] --------------------------------[ jar ]---------------------------------
            [INFO]
            [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ DataLib ---
            [INFO] Deleting D:\Workshop\maven\MavenDemo04\DataLib\target
            [INFO]
            [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ DataLib ---
            [WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
            [INFO] skip non existing resourceDirectory D:\Workshop\maven\MavenDemo04\DataLib\src\main\resources
            [INFO]
            [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ DataLib ---
            [INFO] Changes detected - recompiling the module!
            [WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent!
            [INFO] Compiling 1 source file to D:\Workshop\maven\MavenDemo04\DataLib\target\classes
            [INFO]
            [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ DataLib ---
            [WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
            [INFO] skip non existing resourceDirectory D:\Workshop\maven\MavenDemo04\DataLib\src\test\resources
            [INFO]
            [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ DataLib ---
            [INFO] Changes detected - recompiling the module!
            [WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent!
            [INFO] Compiling 1 source file to D:\Workshop\maven\MavenDemo04\DataLib\target\test-classes
            [INFO]
            [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ DataLib ---
            [INFO] Surefire report directory: D:\Workshop\maven\MavenDemo04\DataLib\target\surefire-reports

            -------------------------------------------------------
            T E S T S
            -------------------------------------------------------
            Running com.example.AppTest
            Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec

            Results :

            Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

            [INFO]
            [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ DataLib ---
            [INFO] Building jar: D:\Workshop\maven\MavenDemo04\DataLib\target\DataLib-1.0.jar
            [INFO]
            [INFO] --- maven-install-plugin:2.4:install (default-install) @ DataLib ---
            [INFO] Installing D:\Workshop\maven\MavenDemo04\DataLib\target\DataLib-1.0.jar to C:\Applications\Java\maven-repository\com\example\DataLib\1.0\DataLib-1.0.jar
            [INFO] Installing D:\Workshop\maven\MavenDemo04\DataLib\pom.xml to C:\Applications\Java\maven-repository\com\example\DataLib\1.0\DataLib-1.0.pom
            [INFO] ------------------------------------------------------------------------
            [INFO] BUILD SUCCESS
            [INFO] ------------------------------------------------------------------------
            [INFO] Total time:  9.294 s
            [INFO] Finished at: 2022-06-07T16:01:35+08:00
            [INFO] ------------------------------------------------------------------------

复制代码

        通过以上执行结果,我们看到 maven-source-plugin:jar-no-fork 目标并没有被调用。

        在 DataLib 的 POM 文件中添加 plugin 元素声明需要调用的插件。

复制代码

 1             <project> 2                 ... 3  4                 <build> 5                     <pluginManagement> 6                         ... 7                     </pluginManagement> 8                     <plugins> 9                         <plugin>10                             <groupId>org.apache.maven.plugins</groupId>11                             <artifactId>maven-source-plugin</artifactId>12                         </plugin>13                     </plugins>14                 </build>15             </project>

复制代码

        与依赖管理相似,由于 pluginManagement 元素中已经包含了插件的全部信息,所以当使用 plugins 元素声明插件调用时,只需要声明插件的 groupId 和 artifactId 即可。

        再次执行命令 mvn clean install,显示结果里 maven-source-plugin:jar-no-fork 目标被成功调用。

    2) 继承插件依赖

        当项目中的多个模块存在相同的插件时,应当将插件配置移动到父模块的 pluginManagement 元素中。即使各个模块对于同一插件的具体配置不尽相同,也应当在父模块中使用 pluginManagement 元素对插件版本进行统一声明。

        可以将项目中所有插件的版本信息都在父模块的 POM 中声明,子模块中不再配置任何的版本信息,这样不仅可以统一项目的插件版本,还可以避免出现版本冲突或插件不稳定等问题。

        例如,将 DataLib 中 pluginManagement 元素中的配置内容移动到父模块 MavenDemo04 的 POM 中,具体配置入下。

复制代码

 1             <project xmlns="http://maven.apache.org/POM/4.0.0" 2                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3                     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 4                                         https://maven.apache.org/xsd/maven-4.0.0.xsd"> 5  6                 <modelVersion>4.0.0</modelVersion> 7                 <groupId>com.example</groupId> 8                 <artifactId>MavenDemo04</artifactId> 9                 <version>1.0</version>10                 <packaging>pom</packaging>11                 <properties>12                     <!-- 定义 Maven 变量 -->13                     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>14                     <log4j.version>1.2.17</log4j.version>15                     <junit.version>3.8.1</junit.version>16                     <system.version>1.0</system.version>17                     <mariadb.client.version>2.7.4</mariadb.client.version>18                 </properties>19 20                 <dependencyManagement>21                     ...22                 </dependencyManagement>23 24                 <build>25                     <pluginManagement>26                         <plugins>27                             <plugin>28                                 <groupId>org.apache.maven.plugins</groupId>29                                 <artifactId>maven-source-plugin</artifactId>30                                 <version>3.2.1</version>31                                 <executions>32                                     <execution>33                                         <id>com.example-parent</id>34                                         <phase>verify</phase>35                                         <goals>36                                             <goal>jar-no-fork</goal>37                                         </goals>38                                     </execution>39                                 </executions>40                             </plugin>41                         </plugins>42                     </pluginManagement>43                 </build>44             </project>

复制代码

        在 DataLib 的 POM 中使用 parent 元素继承 MavenDemo04 ,并声明使用 maven-source-plugin 插件,配置如下。

复制代码

 1             <project xmlns="http://maven.apache.org/POM/4.0.0" 2                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3                     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 4                                         https://maven.apache.org/xsd/maven-4.0.0.xsd"> 5  6                 <modelVersion>4.0.0</modelVersion> 7                 <artifactId>DataLib</artifactId> 8                 <parent> 9                     <groupId>com.example</groupId>10                     <artifactId>MavenDemo04</artifactId>11                     <version>1.0</version>12                 </parent>13                 <dependencies>14                     <dependency>15                         <groupId>junit</groupId>16                         <artifactId>junit</artifactId>17                     </dependency>18                 </dependencies>19                 <build>20                     <plugins>21                         <!-- 声明使用 maven-source-plugin 插件 -->22                         <plugin>23                             <groupId>org.apache.maven.plugins</groupId>24                             <artifactId>maven-source-plugin</artifactId>25                         </plugin>26                     </plugins>27                 </build>28             </project>

复制代码

        打开 cmd 命令行窗口,进入 D:\Workshop\maven\MavenDemo04\DataLib 目录,执行以下命令:

            D:\Workshop\maven\MavenDemo04\DataLib>mvn clean install

        显示结果如下:

复制代码

            ...

            [INFO]
            [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ DataLib ---
            [INFO] Building jar: D:\Workshop\maven\MavenDemo04\DataLib\target\DataLib-1.0.jar
            [INFO]
            [INFO] --- maven-source-plugin:3.2.1:jar-no-fork (com.example-parent) @ DataLib ---
            [INFO] Building jar: D:\Workshop\maven\MavenDemo04\DataLib\target\DataLib-1.0-sources.jar
            [INFO]
            [INFO] --- maven-install-plugin:2.4:install (default-install) @ DataLib ---
            [INFO] Installing D:\Workshop\maven\MavenDemo04\DataLib\target\DataLib-1.0.jar to C:\Applications\Java\maven-repository\com\example\DataLib\1.0\DataLib-1.0.jar
            [INFO] Installing D:\Workshop\maven\MavenDemo04\DataLib\pom.xml to C:\Applications\Java\maven-repository\com\example\DataLib\1.0\DataLib-1.0.pom
            [INFO] Installing D:\Workshop\maven\MavenDemo04\DataLib\target\DataLib-1.0-sources.jar to C:\Applications\Java\maven-repository\com\example\DataLib\1.0\DataLib-1.0-sources.jar
            [INFO] ------------------------------------------------------------------------
            [INFO] BUILD SUCCESS
            [INFO] ------------------------------------------------------------------------
            [INFO] Total time:  5.236 s
            [INFO] Finished at: 2022-06-07T16:33:21+08:00
            [INFO] ------------------------------------------------------------------------

复制代码

转自:https://www.cnblogs.com/tkuang/p/16361904.html