从根上理解Maven拉包原理,搞定Maven全功能 上

简介: 从根上理解Maven拉包原理,搞定Maven全功能 上


在一次需求迭代中,我要求同事把写好的 RPC 接口打好包上传到公司私服上,她直接当场懵逼住了。

我突然发现它对于 Maven 仅仅是处于最基础的使用阶段,不仅不知道背后的一些原理,甚至连一些常见的概念都不是很清晰,仅仅会使用 Maven 构建项目,引入依赖,打包等最基础的操作。于是,在公司搞了一次内部培训,帮助大家补补课,也让她成功的完成了需求。我在这里做一个小总结,希望能够帮助到更多的人。

依赖

依赖是我们在使用 Maven 构建项目时最常使用的功能,通过依赖标签,我们可以直接从Maven仓库中引入对应的Jar包,无需手动再将Jar添加到目录下了,可谓是十分方便,不过我们除了使用,还需要考虑多模块下依赖之间的关系。

依赖配置

这个大家应该都很熟悉了,通过<dependency>标签引入Maven依赖

<dependencies> 
 <!-- servlet包 -->
     <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
     </dependency>
</dependencies>

引入依赖之后,刷新一下Maven依赖就可以引入相关的Jar包了。

依赖传递

依赖具有传递性,当我们引入了一个依赖的时候,就会自动引入该依赖引入的所有依赖,依次往下引入所有依赖。

比如我们引入了Druid数据库连接池的SpringBoot-Starter,那么就会自动引入一些依赖

依赖传递

如图,我们仅仅引入了druid-spring-boot-starter依赖,就自动引入了该依赖依赖的依赖。总而言之就是套娃就完事了。

我们将这三个依赖称为间接引入的依赖,而我们在<dependency>标签中引入的依赖称为直接依赖,那么如果这两个重复了并且版本不一样的话会怎么办呢,最后引入的到底是哪个版本呢,还是说都会引入呢?

如果重复了,遵从以下规则

Maven依赖重复后遵的规则

简单来说,就是越在外层的优先级越高,如果同级的就按照配置顺序,配置顺序靠前的覆盖配置顺序靠后的。

可选依赖

可选依赖指对外隐藏当前所依赖的资源

<dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>4.12</version>
 <optional>true</optional>
</dependency>

配置了该选项之后,间接依赖就失效了。

排除依赖

排除依赖指主动断开间接依赖的资源

<dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>4.12</version>
 <exclusions>
  <exclusion>
   <groupId>org.hamcrest</groupId>
   <artifactId>hamcrest-core</artifactId>
  </exclusion>
 </exclusions>
</dependency>

配置了该选项之后,间接依赖也会失效。

排除依赖和可选依赖的区别:

可选依赖是依赖提供者设置的,比如我们引入了Durid,那么该选项由Durid开发者设置

排除依赖由依赖引入者设置,比如我们引入了Durid,那么我们可以设置该选项

依赖范围

依赖的jar默认情况可以在任何地方使用,可以通过scope标签来改变依赖的作用范围。

依赖范围

主代码指的是main文件夹下的代码,测试代码指的是test文件夹下的代码(就那个绿色的玩意),打包指的是maven package指令执行时是否将Jar包打包。

其实如果我们偷懒的话,全部都默认也不是不可能,不过为了我们程序代码的可读性与简洁性,还是按照规范来比较好。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

生命周期与插件

项目构建生命周期

Maven项目构建生命周期描述的是一次构建过程经历了多少个事件,我们可以把生命周期当成一个人的年龄。

Maven将生命周期划分为三个大阶段,类似于人类的婴儿,青年,入土

  • clean:清理工作
  • default:核心工作,例如编译,测试,打包,部署
  • site:产生报告,发布站点

第一个和第三个周期比较简单,我们重点介绍一下default阶段

先上一张劝退图

劝退图

以上就是defalut阶段完整的生命周期,其中标红的地方,是几个比较重要的周期,在Idea的Maven工具中也能体现出来

maven生命周期

当我们在Idea中点击这几个生命周期时,Maven会自动将之前所有的生命周期都执行到,就类似于如果我18岁了,那么我肯定经历过8岁。

插件

插件就是Idea中Maven工具的Plugins部分

Maven插件

通过pom文件中的<build></build>标签引入新的插件

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
</build>

那么什么是插件呢?

  • 「插件与生命周期内的阶段绑定」 ,在「执行到对应生命周期时执行对应的插件功能」
  • 默认maven在各个生命周期上绑定有预设的功能
  • 通过插件可以自定义其他功能
<build>
    <plugins>
            <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-source-plugin</artifactId>
                    <version>2.2.1</version>
                    <executions>
                            <execution>
                                    <goals>
                                            <goal>jar</goal>
                                    </goals>
                                    <phase>generate-test-resources</phase>
                            </execution>
                    </executions>
            </plugin>
    </plugins>
</build>

上述自定义插件的作用指的是在generate-test-resources生命周期执行打jar包的操作。

其实简单的说,生命周期就是一个人的年龄阶段,而插件就是每个人在每个年龄需要做的事情

总结:

总结

Maven将一个项目构建的过程分为一长串连续的生命周期,在对应的生命周期会通过插件完成对应的事件,通过使用Maven的生命周期,我们可以获得我们需要的功能,可能是打jar包,可能是安装到本地仓库,可能是部署到私服。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

模块聚合

当使用Maven进行多模块开发的时候,有可能出现A模块依赖B模块,B模块依赖C模块,那么我们如果想对A模块打包,那么就要先打包C模块,再打包B模块,最后打包A模块才能成功,否则会报错,并且,如果C模块更新了,我们也要手动更新所有依赖C模块的模块,这样是及不方便的,Maven为了更好的进行多模块开发,提供了模块聚合的功能。

作用:「聚合用于快速构建Maven工程,一次性构建多个项目/模块」

  • 使用步骤,我们用开源项目ruoyi的项目结构来看一下聚合在ruoyi中的使用
  1. 项目结构
  2. RuoYi-Vue父模块的pom文件
<!--聚合的所有模块-->
<modules>
        <module>ruoyi-admin</module>
        <module>ruoyi-framework</module>
        <module>ruoyi-system</module>
        <module>ruoyi-quartz</module>
        <module>ruoyi-generator</module>
        <module>ruoyi-common</module>
</modules>
<!--打包类型定义为pom-->
<packaging>pom</packaging>
  1. 直接对打包类型为pom的模块进行生命周期的管理,Maven会自动帮我们管理聚合的所有模块的生命周期,操作顺序跟依赖顺序有关系。

模块继承

还是在多模块项目开发中,多个子模块可能会引入相同的依赖,但是他们有可能会各自使用不同的版本,版本问题,有可能会导致最后构建的项目出问题,所以我们需要一种机制,来约定子模块的相关配置,于是就有了模块继承

作用:通过继承可以实现在子工程中沿用父工程中的配置

实现步骤:还是以ruoyi为例

  1. 在子工程中声明其父工程坐标与对应的位置
 <parent>
        <artifactId>ruoyi</artifactId>
        <groupId>com.ruoyi</groupId>
        <version>3.8.1</version>
 </parent>
  1. 在父工程中定义依赖管理
<dependencyManagement>
        <dependencies>
            <!-- SpringBoot的依赖配置-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.5.8</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 阿里数据库连接池 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <!-- SpringBoot集成mybatis框架 -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis-spring-boot.version}</version>
            </dependency>
            <!-- pagehelper 分页插件 -->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pagehelper.boot.version}</version>
            </dependency>
    </dependencies>
</dependencyManagement>
  1. 定义完成之后,子工程相关的依赖就无需定义版本号,会直接使用父工程的版本号
<dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>

继承除了依赖版本号之外,还会继承一些资源,如下图

模块继承

相关文章
|
8月前
|
druid Java 数据库连接
一文带你搞定Maven全功能
在一次需求迭代中,同事要求我把写好的RPC接口打好包上传到公司私服上,我人直接当场懵逼住了。
|
11天前
|
缓存 弹性计算 Java
云效产品使用报错问题之maven仓设置为私有后,赋予成员权限未生效,拉包401要如何解决
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
|
10月前
|
Java 测试技术 Maven
maven打包全流程原理
maven打包全流程原理
315 0
|
11月前
|
Java 应用服务中间件 测试技术
spring-Bean管理-springboot原理-Maven高级
配置优先 级优先级(低→高) application.yaml(忽略) application.yml application.properties java系统属性(-Dxxx=xxx) 命令行参数(–xxx=xxx) Bean管理
|
Java 测试技术 Maven
从根上理解Maven拉包原理,搞定Maven全功能 下
从根上理解Maven拉包原理,搞定Maven全功能 下
|
Java 关系型数据库 测试技术
Maven 核心原理
Maven 核心原理 标签 : Java基础 Maven 是每一位Java工程师每天都会接触的工具, 但据我所知其实很多人对Maven理解的并不深, 只把它当做一个依赖管理工具(下载依赖、打包), Maven很多核心的功能反而没用上.
1703 0
|
缓存 Java 应用服务中间件
Rainbond构建Java Maven项目原理解读(CI)
本文从流程、原理上解读Rainbond平台如何从Java Maven源代码持续构建服务。
1462 0
|
Java 应用服务中间件 Maven
jetty服务器原理与maven集成
jetty服务器原理+MyEclipse下与Maven集成 Jetty 是一个开源的servlet容器,它为基于Java的web容器,例如JSP和servlet提供运行环境。Jetty是使用Java语言编写的,它的API以一组JAR包的形式发布。
1351 0
|
2月前
|
Java Maven
手把手教你搭建Maven项目
手把手教你搭建Maven项目
31 0

热门文章

最新文章

推荐镜像

更多