Maven高级

117 阅读6分钟

一,分模块思路

分模块开发就是将我们一整个完整的项目拆解为多个模块,方便团队开发。如下图所示:

image-20230923194053925

每一个模块都对应一个单独的pom文件,然后在使用的时候我们直接把每个模块当成外部jar包,需要使用的时候直接在自己的pom文件中导入对应的坐标即可。

在拆解完毕后,需要删除跟这个模块无关的配置文件,无关的依赖,只留下与该模块所需的相关依赖。

注意:在拆解好模块后需要在生命周期中install一下上传到我们本地仓库中,如果存在私服就deploy上去才能正常使用这些拆解的模块。

二,Maven聚合

假设我们将一个大模块拆解为多个小模块,并且A--依赖----->B--依赖----->C----依赖--->D

假设C模块更新了并且install到了本地仓库,此时会其他模块并不知道C模块更新了,可能会导致项目崩溃。

解决办法:通过聚合,只要模块中任意一个模块更新了,其他模块都一起更新。

聚合方法:创建一个新模块,里面只有pom文件,用来管理全部模块。

如下图:

image-20230923194836546

pom文件主要标签

<?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.normaling</groupId>
    <artifactId>BlogManager-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    
	<!-- 声明子模块列表 -->
    <modules>
        <module>ManagerModel</module>
    </modules>

</project>

假设在模块中存在A--依赖----->B--依赖----->C----依赖--->D这种关系,那么我们通过模块进行编译的时候,会按照A,B,C,D这个顺序进行编译。如果不是这种线性依赖,那么就会按照我们配置的顺序进行编译。

packagin标签的值有:

  • pom表明这个工程是用于构建管理的。
  • jar表明这个是打jar包,资源包
  • war表面这个是打war包,网页相关的

三,继承

如下图,当我们的service模块使用的是5.1.9版本,dao模块使用的是5.2.0版本,如果两个版本的spring-context不兼容,那就可能会导致项目崩溃。

image-20230923195524526

解决方法:在用于构建管理的那个模块中选择指定版本的spring-context版本,在其他模块中只指定要用这个模块,但不指定模块具体版本。

image-20230923195631579

这个就是继承。


使用方法:

  1. 在父工程中导入这个项目需要使用的所有依赖

    <?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.normaling</groupId>
        <artifactId>BlogManager-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>pom</packaging>
        
        <!-- 声明子模块列表 -->
        <modules>
            <module>ManagerModel</module>
        </modules>
    
        <dependencyManagement>
            <dependencies>
               <!--需要统一管理的模块坐标-->
            </dependencies>
        </dependencyManagement>
    
        <!-- 插件管理 -->
        <build>
            <pluginManagement>
                <plugins>
                     <!--需要统一管理的插件坐标-->
                </plugins>
            </pluginManagement>
        </build>
    
    </project>
    
  2. 在子工程中定义该工程的父工程的坐标

    <?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>
    
        <parent>
            <groupId>com.normaling</groupId>
            <artifactId>BlogManager-parent</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <!--父工程的相对路径的pom文件-->
            <relativePath>../pom.xml</relativePath>
        </parent>
    
        <artifactId>ManagerModel</artifactId>
    
        <properties>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
    
        <dependencies>
            <!--子模块需要使用的依赖-->
        </dependencies>
    
    
        <!-- 插件管理 -->
        <!-- 我们在子模块导入时如果需要单独为子模块配置,就直接在子模块显示配置即可,配置会覆盖的-->
        <build>
            <plugins>
                <!-- 编译插件 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                </plugin>
                <!-- Spring Boot 打包插件 -->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <skip>false</skip><!--跳过打包,这里需要false,因为子模块实际有内容-->
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    注意:

    • 删除子工程的groupId标签和version。因为子工程和父工程是同一个组织,同一个版本。
    • 删除子工程所有的依赖的版本version标签和插件的version,统一交给父工程管理。
    • 我们自己拆好的模块记得也要导入到依赖管理之中进行管理。

子工程可以继承的标签如下:

image-20230923201830187


四,属性

通过上述的继承和聚合之后,我们将整个项目的依赖管理全部集中到了父工程的pom文件中,假设我们要对某一特定依赖的版本进行更新,可能需要对其他的模块统一进行更新,但是一个个找就可能会出现漏掉更新的模块。

解决方法就是:通过在maven中设置属性,用属性存储具体的版本信息,将所有的依赖使用属性统一进行管理。

属性的类别:

  1. 自定义属性

    作用:等同于java中的变量,方便不同依赖之间的统一维护。

    使用方法:在父工程中定义<properties></properties>

    <!--定义自定义属性-->
    <properties>
        <!--命名方法:模块名.version-->
    	<spring.version>spring模块的版本</spring.version>
        <junit.version></junit.version>
    </properties>
    

    调用方法:${自定义属性名}

    <dependency>
    	<groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    
  2. 内置属性

    作用:使用maven内置属性,比如说在父工程中,父工程内部的坐标标签的值]

    调用方法:

    ${basedir}
    <!--父工程坐标的version标签值-->
    ${version}
    
  3. Setting属性

    作用:使用maven配置文件setting.xml中的标签属性,用于动态配置

    调用方法:

    ${settings.属性名}
    
  4. Java系统属性

    作用:读取Java系统属性

    使用方法:

    ${系统属性名}
    
  5. 环境变量

    作用:使用maven配置文件setting.xml中的标签属性,用于动态配置

    调用方法:

    ${env.环境属性名}
    

系统属性查询方式和环境变量属性查询方法:

mvn help:system

image-20230923211511778

填入等号前面的属性名即可获得属性值。


五,版本命名

Maven工程版本分为两个版本(每个公司定义的版本号都有区别,实际按照规则要求命名即可)

  • SNAPSHOT(快照版本:maven工程版本默认就是这个)

    项目开发过程中,为方便团队成员合作,解决模块间相互依赖和时间更新的问题,开发者对每个模块进行构建的时候,输出的临时版本,快照版本UI随着开发的进展不断更新

  • RELEASE(发布版本)

    项目开发到进入阶段里程碑后,向团队外部发布较为稳定的版本,这种版本对应的构建文件是稳定的,即便进行功能的后续开发,也不会改变当前发布版本的内容


工程版本号,约定规范 <主版本>.<次版本>.<增量版本>.<里程碑版本>,例如5.1.9.RELEASE

  • 主版本:表示项目重大架构的变更,如:spring5和springboot2相较于spring4和springboot1的迭代
  • 次版本:表示有较大的功能增加和变化,或者全面系统地修复漏洞
  • 增量版本:表示有重大漏洞的修复
  • 里程碑版本:表明一个版本的里程碑(版本内部),这样的版本同下一个正式版本相比,相对来说不是很稳定,需要更多的测试

六,资源配置

我们在Spring工程里面的yaml配置文件编写的dbc.driverjdbc.url等,也可以通过maven直接配到pom.xml中进行统一的配置。

这个就是资源配置。

使用方法:

  1. 在pom.xml文件中:

      <properties>
        <jdbc.url>jdbc:mysql://127.0.0.1:3306/srb</jdbc.url>
        <jdbc.username>root</jdbc.username>
      </properties>
    
    
    
      <build>
       <!--配置资源文件对应的信息-->
        <resources>
          <resource>
            <!--路径,一定要对,${project.basedir}项目路径为maven自带属性,方便配置所有的模块。-->
            <directory>${project.basedir}/src/main/resources</directory>
            <!--参与过滤,false不解析,打包的时候就是配的值(${jdbc.url})-->
            <filtering>true</filtering>
          </resource>
        </resources>
          
        <!--测试资源,路径不是main,是test-->
        <testResources>
          <testResource>
            <directory>${project.basedir}/src/test/resources</directory>
            <filtering>true</filtering>
          </testResource>
        </testResources>
          
      </build>
    
  2. 在原始yaml配置文件中:

    jdbc:
     url: ${jdbc.url}
     username: ${jdbc.username}
    

    不推荐这种写法,了解即可。

七,跳过测试

image-20230924153107823

跳过测试有三种方法:

  1. idea自带选项点击即可

    image-20230924153309486

  2. 使用maven命令跳过测试

    mvn 指定maven生命周期 -D skipTests
    
  3. 配置pom文件来跳过测试

    <build>
    	<pluginManagement>
        	<plugins>
                <!--配置跳过测试-->
            	<plugin>
                    <!--测试插件的坐标-->
                	<groupId>org.apache.maven</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>你测试插件的版本,具体去看maven仓库查就行了</version>
                    <configuration>
                        <!--设置整个项目都跳过测试-->
                    	<skipTests>true</skipTests>
                        
                        <!--包含指定测试用例要进行测试-->
                        <includes>
                            <!--**代表任意包-->
                        	<include>**/UserServiceTest.java</include>
                        </includes>
                        <!--排除指定测试用例要进行测试-->
                        <excludes>
                        	<exclude>
                                
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
    

八,外部下载的jar包安装到本地仓库

在写的时候我发现有时候我们需要外接类似阿里云OSS的sdk的jar包,但是如果你直接去写坐标是没用的,因为外部仓库是不存在这个jar包的,所有可以采用先下载这个jar包然后安装到本地即可。当然安装到私服也是可以的。

mvn install:install-file
-Dfile=spring.jar //jar包名称
-Dartifactld=spring //jar包源项目的artifactid
-DgroupId=com.fpl //jar包源项目的groupid
-Dversion=1.0-SNAPSHOT //jar包源项目的version
-Dpackaging=jar

九,拆分项目注意要点

  1. 父模块

    <?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.normaling</groupId>
        <artifactId>BlogManager-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>pom</packaging>
    
        <!-- 声明子模块列表 -->
        <modules>
            <module>ManagerModel</module>
        </modules>
    
    
        <!-- 统一属性管理 -->
        <properties>
            <java.version>17</java.version>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <spring-boot.version>3.0.2</spring-boot.version>
            <mybatis.version>3.0.0</mybatis.version>
            <mysql.version>8.0.33</mysql.version>
            <lombok.version>1.18.26</lombok.version>
        </properties>
    
        <dependencyManagement>
            <dependencies>
                <!-- Spring Boot BOM -->
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>${spring-boot.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!--lombok管理-->
                <dependency>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                    <version>${lombok.version}</version>
                    <optional>true</optional>
                </dependency>
                <!-- MyBatis -->
                <dependency>
                    <groupId>org.mybatis.spring.boot</groupId>
                    <artifactId>mybatis-spring-boot-starter</artifactId>
                    <version>${mybatis.version}</version>
                </dependency>
                <!-- MySQL -->
                <dependency>
                    <groupId>com.mysql</groupId>
                    <artifactId>mysql-connector-j</artifactId>
                    <version>${mysql.version}</version>
                    <scope>runtime</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <!-- 插件管理 -->
        <build>
            <pluginManagement>
                <plugins>
                    <!-- 编译插件 -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <configuration>
                            <source>${java.version}</source>
                            <target>${java.version}</target>
                            <encoding>${project.build.sourceEncoding}</encoding>
                        </configuration>
                    </plugin>
                    <!-- Spring Boot 打包插件 -->
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                        <version>${spring-boot.version}</version>
                        <configuration>
                            <skip>true</skip>  <!-- 默认跳过,子模块按需启用 -->
                        </configuration>
                    </plugin>
                </plugins>
            </pluginManagement>
        </build>
    
    </project>
    
  2. 子模块

    <?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>
    
        <parent>
            <groupId>com.normaling</groupId>
            <artifactId>BlogManager-parent</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <!--父工程的相对路径的pom文件-->
            <relativePath>../pom.xml</relativePath>
        </parent>
    
        <artifactId>ManagerModel</artifactId>
    
    
    
        <dependencies>
            <!--SpringWeb依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--lombok管理-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <!-- MyBatis -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
            </dependency>
            <!-- MySQL -->
            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <scope>runtime</scope>
            </dependency>
        </dependencies>
    
    
        <!-- 插件管理 -->
        <build>
            <plugins>
                <!-- 编译插件 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                </plugin>
                <!-- Spring Boot 打包插件 -->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <skip>false</skip>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    
    </project>
    
  3. 注意要点:

    • 我们父模块的SpringBoot依赖管理有两种方式

      特性<parent> 继承方式<dependencyManagement> + BOM 导入方式
      核心作用继承父 POM 的配置(依赖、插件、属性等)仅导入依赖版本管理,不继承其他配置
      灵活性强制继承所有配置,可能与其他父 POM 冲突更灵活,允许项目有自己的父 POM
      适用场景单模块项目或明确需要 Spring Boot 作为父级的情况多模块项目、已有自定义父 POM 的项目
      依赖版本管理自动继承所有 Spring Boot 管理的依赖版本需显式导入 BOM,但版本仍由 Spring Boot 统一管理

      上述讲的是parent继承方式,但SpringBoot已经改成Bom导入方式了,所以我们这边也改成这样

    • Bom导入后我们父依赖不需要显示导入SpringBootWeb依赖,因为它里面已经有了,我们只需要在子模块中引入即可

    • 关于Maven插件中skip配置,在父模块需要开启,在子模块中统一禁用它

  4. 在分模块后,例如Mybatis的mapper文件,一般每个模块都有一个的,但是这样包扫描的时候会扫描不到,我们需要在pom里面

    1. 在父模块依赖管理都管理这些子模块

    2. 在子模块中启动类那个模块依赖这些所有的子模块