【4】Gradle-快速入门使用【Gradle多模块项目详解】

目录

  • 【4】Gradle-快速入门使用【Gradle多模块项目详解】
    • 创建多项目构建
    • 添加子项目
      • 命名建议
    • 项目依赖项
      • 项目路径
      • 不同模块的`build.gradle`配置
    • 子项目之间共享构建逻辑
      • 公约插件
      • 跨项目配置
      • buildSrc开发公约插件
    • 调整多模块项目配置
        • 修改项目树的元素
    • 了解Gralde配置时间和执行时间
      • 并行项目执行
      • 解耦项目

个人主页: 【⭐️个人主页】
需要您的【💖 点赞+关注】支持 💯


在这里插入图片描述

【4】Gradle-快速入门使用【Gradle多模块项目详解】

📖 本文核心知识点:

  • 多模块项目
  • 多模块添加子项目
  • 多模块全局配置方式
  • 多模块间依赖
  • 多模块项目调整
  • 多模块buildSrc目录
  • 多模块配置时间和执行时间
  • 并行执行和解耦合

创建多项目构建

Gradle中的多项目构建由一个根项目一个或多个子项目组成。

基本的多项目构建包含一个根项目和一个子项目。这是一个多项目构建的结构,它包含一个名为app的子项目:

├── app
│   ...
│   └── build.gradle
└── settings.gradle

这是启动任何Gradle项目的推荐项目结构。build init插件还会生成遵循这种结构的框架项目——一个根项目和一个子项目。

🅰️ 注意:根项目没有Gradle构建文件build.gradle,只有一个定义要包含的子项目的设置文件settings.gradle
settings.gradle

rootProject.name = 'basic-multiproject'
include 'app'

在这种情况下,Gradle将在app目录中查找构建文件。

我们可以通过运行gradlew projects命令来查看多项目构建的结构
在这里插入图片描述
使用 gradle -q run命令,启动app项目

添加子项目

假设我们想要在前面创建的项目中添加另一个名为infrastructure的子项目。我们所需要做的就是在根设置文件中添加另一个include语句:
settings.gradle

rootProject.name = 'study-spring3'
include 'app'
// 基础设施模块
include 'infrastructure'

结构:

.
├── app
│   ...
│   └── build.gradle
├── infrastructure
│   ...
│   └── build.gradle
└── settings.gradle

命名建议

随着项目的发展,命名一致性变得越来越重要。为了保持构建的可维护性,我们建议采用以下方法:

  • 子项目保留默认项目名称:可以在设置文件中配置自定义项目名称。但是,对于开发人员来说,跟踪哪个项目属于哪个文件夹是不必要的额外工作。

  • 对所有项目名称使用kebab大小写格式:

    kebab大小写格式是指所有字母都是小写,单词之间用破折号(' - ')字符分隔(例如kebab-case-formatting)。这已经是许多大型项目的实际模式。此外,Gradle支持kebab case名称缩写。

  • 在设置文件settings.gradle中定义根项目名称``:' rootProject.name '有效地为整个构建分配了一个名称,这在构建扫描等报告中使用。如果没有设置根项目名称,则名称将是容器目录名称,这可能是不稳定的(即您可以将项目签出到任何目录)。如果没有设置根项目名,并且它被检出到文件系统的根目录(例如/或C:),则该名称将随机生成。

项目依赖项

❓ 如果一个项目需要另一个项目在其编译类路径上生成的jar,该怎么办?
❓ 如果它还需要其他项目的传递依赖项怎么办?
显然,这是Java多项目构建中非常常见的用例。正如在项目依赖项中提到的,Gradle为此提供了项目依赖项

├── buildSrc
│   ...
├── api
│   ├── src
│   │   └──...
│   └── build.gradle
├── domain-core
│   ├── src
│   │   └──...
│   └── build.gradle
├── infrastructure
│   ├── src
│   │   └──...
│   └── build.gradle
└── settings.gradle

有三个项目api, domain-core, infrastructure,它们之间的依赖关系是
在这里插入图片描述

我们使用:分隔符来定义项目路径

项目路径

给定的项目添加到构建中。所提供列表中的每个路径都被视为要添加到构建中的项目的路径。注意,这些路径不是文件路径,而是指定新项目在项目层次结构中的位置。因此,所提供的路径必须使用':'字符作为分隔符(而不是’/')。
所提供路径的最后一个元素用作项目名称。提供的路径被转换为相对于根项目目录的项目目录。项目目录可以在项目被包含之后通过改变’projectDir'属性来改变(参见ProjectDescriptor.setProjectDir(java.io.File))

使用项目路径的一些常见示例如下:

// include two projects, 'foo' and 'foo:bar'
// directories are inferred by replacing ':' with '/'
include 'foo:bar'

// include one project whose project dir does not match the logical project path
include 'baz'
project(':baz').projectDir = file('foo/baz')

// include many projects whose project dirs do not match the logical project paths
file('subprojects').eachDir { dir ->
  include dir.name
  project(":${dir.name}").projectDir = dir
}

不同模块的build.gradle配置

  1. app
    dependencies {
           implementation 'org.apache.commons:commons-text'
           implementation project(':infrastructure')
       }
    
  2. infrastructure
    	dependencies {
    	    implementation project(':domain-core')
    	}
    
  3. domain-core 【无】

执行gradle app:dependencies查看app的依赖项
在这里插入图片描述

子项目之间共享构建逻辑

公约插件

通常,多项目构建中的子项目具有一些共同的特征

例如,几个子项目可能包含特定编程语言的代码,而另一个子项目可能专门用于文档。代码质量规则适用于所有代码子项目,但不适用于文档子项目。与此同时,具有共同特征的子项目可能服务于不同的目的——它们可能会产生不同的工件类型来进一步区分它们,
例如:
1. 公共库 : 发布到某些Mavne存储库的库
2. 内部库 :其他子项目在项目内部依赖的库
3. 命令行应用程序 : 具有特定打包要求的应用程序
4. Web服务 : 具有与上述不同的特定包装要求的应用程序
等等
其他一些代码子项目可能专门用于测试目的等。
以上特征标识了子项目的类型。或者换句话说,子项目的类型告诉我们该项目具有哪些特征

所以: 多个特征组成了一类的子项目。一类子项目可以作为公共构建进行子项目间共享。

Gradle推荐组织构建逻辑的方法使用其插件系统

  1. 插件应该定义子项目的类型

    事实上,Gradle核心插件以相同的方式建模
    例如,Java插件配置了一个通用的java项目,而Java库插件在内部应用Java插件,并配置特定于Java库的方面。同样,应用程序插件应用和配置Java插件和分发插件

  2. 您可以通过应用和配置核心和外部插件来编写自定义构建逻辑,并创建自定义插件,定义新的项目类型配置特定于您的项目或组织的约定(特征)。

跨项目配置

另一种令人沮丧的子项目之间共享构建逻辑的方法是通过
subprojects {} allprojects {} DSL结构进行跨项目配置。
通过交叉配置,构建逻辑可以注入子项目,在查看子项目的构建脚本时,这并不明显,这使得理解特定子项目的逻辑更加困难。从长远来看,交叉配置通常会随着越来越多的条件逻辑和更高的维护负担而变得复杂。

交叉配置还可以引入项目之间的配置时间耦合,这可能会阻止按需配置等优化正常工作。
配置时间耦合: 指下载插件和依赖的时间。指多项目构建时,子项目间交叉依赖,耦合在一起。

交叉配置有两种最常见的用途,都可以使用约定插件的方式更好地建替代:

  1. 将插件或其他配置应用于特定类型的子项目。

    通常,如果子项目是X类型,那么交叉配置部分就可以完成,然后配置y。这相当于将X-conventions插件直接应用于子项目。

  2. 从某种类型的子项目中提取信息。此用例可以使用传出的配置变体进行建模。

buildSrc开发公约插件

建议将约定插件源代码和测试放在项目根目录buildSrc目录中。

使用约定插件编写构建逻辑的多项目构建的另一个更复杂和现实的例子是Gradle构建工具本身的构建。

目录buildSrc被视为包含的构建。发现目录后,Gradle会自动编译和测试此代码,并将其放入构建脚本的类路径中。对于多项目构建,只能有一个buildSrc目录,该目录必须位于根项目目录中。buildSrc应优于脚本插件,因为它更容易维护、重构和测试代码

在这里插入图片描述

buildSrc使用适用于Java和Groovy项目的相同源代码约定。它还提供了对Gradle API的直接访问。其他依赖项可以在buildSrc下的专用build.gradle中声明。

可以使用gradle init 生成buildSrc目录。并进行约定插件的gradle编写

调整多模块项目配置

多项目构建总是由具有单个根的树表示树中的每个元素代表一个项目。项目有一个路径,表示项目在多项目构建树中的位置。在大多数情况下,项目路径项目在文件系统中的物理位置一致。然而,这种行为是可配置的。项目树在settings.gradle文件中创建。设置文件的位置也是根项目的位置。

在设置文件中,您可以使用include方法构建项目树。
通过修改settings.gradle文件中的include子项目应用。可以调整子项目的相关信息

include 'project1', 'project2:child', 'project3:child1'

include方法将项目路径作为参数。项目路径假定等于相对的物理文件系统路径。

例如,默认情况下,路径“services:api”映射到文件夹“services/api”(相对于项目根目录)。你只需要指定树的叶子。这意味着包含“services:hotels:api”路径将导致创建3个项目:“services”、“services:hotels”和“services:hotels:api”。

修改项目树的元素
rootProject.name = 'main'
include('project-a')
project(':project-a').projectDir = file('../my-project-a')
project(':project-a').buildFileName = 'project-a.gradle'

了解Gralde配置时间和执行时间

构建阶段描述了每个Gradle构建的阶段。让我们放大多项目构建的配置和执行阶段

这里的配置意味着评估项目的构建脚本文件,其中包括下载所有插件和构建脚本依赖项

默认情况下,所有项目的配置发生在执行任何任务之前。这意味着,当请求来自单个项目的单个任务时,首先配置多项目构建的所有项目。每个项目都需要配置的原因是Gradle项目模型的任何部分 访问和更改 的灵活性

并行项目执行

并行执行试图:

  1. 减少执行受IO绑定或以其他方式不会消耗所有可用CPU资源的多项目构建的总构建时间
  2. 为小型项目的执行提供更快的反馈,而无需等待其他项目的完成。

并行项目执行允许并行执行解耦多项目构建中的独立项目(另见解耦项目)。虽然并行执行在配置时并不严格要求解耦,但长期目标是提供一套强大的功能,这些功能将可用于完全解耦的项目。这些功能包括:

  • 按需配置。
  • 并行配置项目。
  • 为不变的项目重复使用配置。
  • 项目级最新检查。
  • 在构建依赖项目的地方使用预先建造的工件。

并行执行是如何工作的?

首先,您需要告诉Gradle使用并行模式。您可以使用--parallel命令行参数或配置构建环境(Gradle属性)。除非您提供特定数量的并行线程,否则Gradle会尝试根据可用的CPU内核选择正确的数量。每个并行工作线程在执行任务时都只拥有给定的项目。任务依赖性得到完全支持,并行工作线程将首先开始执行上游任务。请记住,在并行模式下,不能保证解耦任务的字母顺序,如在顺序执行过程中所示。换句话说,在并行模式下,任务一旦其依赖项完成,任务工作线程可以运行它们,任务将立即运行,这可能比它们在顺序构建期间开始时更早。您应该确保正确声明任务依赖项和任务输入/输出,以避免订购问题。

解耦项目

Gradle允许任何项目在配置和执行阶段访问任何其他项目。

如果两个项目不直接访问彼此的项目模型,它们就会脱钩。解耦的项目只能在声明的依赖项方面进行交互:项目依赖项和/或任务依赖项。任何其他形式的项目交互(即通过修改另一个项目对象或从另一个项目对象读取值)都会使项目耦合。在配置阶段耦合的后果是,如果使用“按需配置”选项调用gradle,构建的结果可能会在几个方面存在缺陷。执行阶段耦合的后果是,如果使用并行选项调用gradle,一个项目任务运行得太晚,无法影响并行项目构建的任务。Gradle不会试图检测耦合并警告用户,因为引入耦合的可能性太多。

项目耦合的一种非常常见的方法是使用配置注入。它可能不会立即显现出来,但使用allprojectssubprojects关键字等关键Gradle功能会自动使您的项目耦合。这是因为这些关键字用于定义项目的 build.gradle文件中。通常,这是一个“根项目”,只不过定义了通用配置,但就Gradle而言,这个根项目仍然是一个成熟的项目,通过使用allprojects,该项目有效地与所有其他项目耦合。将根项目耦合到子项目不会影响按需配置,但在任何子项目的build.gradle文件中使用allprojects和subprojects都会产生影响

为了充分利用跨项目配置,而不会出现并行和“按需配置”选项的问题,请遵循以下建议:

  • 避免子项目的构建脚本引用其他子项目;更喜欢从根项目进行交叉配置。
  • 避免在执行时更改其他项目的配置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/138003.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SparkSQL之Catelog体系

按照SQL标准的解释,在SQL环境下Catalog和Schema都属于抽象概念。在关系数据库中,Catalog是一个宽泛的概念,通常可以理解为一个容器或数据库对象命名空间中的一个层次,主要用来解决命名冲突等问题。 在Spark SQL系统中,…

从管易云到金蝶云星空通过接口配置打通数据

从管易云到金蝶云星空通过接口配置打通数据 接通系统:管易云 管易云是金蝶旗下专注提供电商企业管理软件服务的子品牌,先后开发了C-ERP、EC-OMS、EC-WMS、E店管家、BBC、B2B、B2C商城网站建设等产品和服务,涵盖电商业务全流程。 接通系统&…

创建maven的 java web项目

创建maven的 java web项目 创建出来的项目样子 再添加java和resources文件夹 一定要如图有文件夹下有图标才代表被IDEA识别,不让是不行的 没有的话在File——ProjectStructure中进行设置

SM8081是一个高效率的1.5MHz同步步进降压DC/DC调节器,可提供高达1A的电压输出电流。

SM8081 高效率,1.5MHZ,1A 同步降压调节器 概述: SM8081是一个高效率的1.5MHz同步步进降压DC/DC调节器,可提供高达1A的电压输出电流。它可以在宽输入电压下工作范围从2.5V到5.5V,集成主开关以及具有非常低Rps&#x…

GPT Store上线 OpenAI 的「iPhone时刻」这回真来了

OpenAI首届全球开发者大会上,Sam Altman再次给AI行业扔了一系列重磅炸弹。GPT-4 Turbo、GPT Store和定制化的GPT在大会上发布,OpenAI的生态体系初具雏形。 GPT模型刚升级了不到24小时,高能网友就开始用它的定制化功能创造了各种有趣的应用。…

kafka实践-热点数据展示

1 实时流式计算 1.1 概念 流式计算一般对实时性要求较高,同时一般是先定义目标计算,然后数据到来之后将计算逻辑应用于数据。同时为了提高计算效率,往往尽可能采用增量计算代替全量计算。也就是将数据先聚集在集中全量处理。 2.2 应用场景…

【网络】TCP协议理论

TCP协议理论 一、TCP协议简介1、浅谈可靠性2、UDP协议存在的意义 二、TCP的协议格式TCP的解包和分用 三、确认应答机制一种应答方式——捎带应答 四、超时重传机制超时等待时间 五、流量控制1、TCP的缓冲区2、TCP的窗口大小3、TCP的PSH标志位 六、TCP的六个标志位URG字段的详细…

操作系统概念

一、是什么 操作系统(Operating System,缩写:OS)是一组主管并控制计算机操作、运用和运行硬件、软件资源和提供公共服务来组织用户交互的相互关联的系统软件程序,同时也是计算机系统的内核与基石 简单来讲&#xff0…

C语言之认识柔性数组(flexible array)

在学习之前,我们首先要了解柔性数组是放在结构体当中的,知道这一点,我们就开始今天的学习吧! 1.柔性数组的声明 在C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员 这里的结构是结构…

Producer

Producer开发样例 版本说明 新客 户端, 从Kafka 0.9.x 开始, client基于Java语言实现。同时提供C/C, Python等其他客户端实现。 开发步骤 配置客户端参数以及创建客户端实例;构建待发送消息;发送消息;关闭生产者实例; 代码示例 public class KafkaProducer {public stati…

C++标准模板(STL)- 类型支持 (受支持操作,检查类型是否有拥有移动赋值运算符)

类型特性 类型特性定义一个编译时基于模板的结构&#xff0c;以查询或修改类型的属性。 试图特化定义于 <type_traits> 头文件的模板导致未定义行为&#xff0c;除了 std::common_type 可依照其所描述特化。 定义于<type_traits>头文件的模板可以用不完整类型实例…

视频剪辑:掌握视频封面提取与剪辑技巧,提升视频传播效果

在数字媒体时代&#xff0c;视频已成为人们获取信息、娱乐和交流的重要方式。而一个吸引人的视频封面往往能吸引更多的观众点击观看&#xff0c;因此&#xff0c;掌握视频封面提取与剪辑技巧对于提升视频传播效果至关重要。视频封面是视频的“门面”&#xff0c;它不仅展示视频…

Vue.js中的路由(router)和Vue Router的作用?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

牛客刷题记录11.12

继承和组合 二进制数统计 1的个数 和 0 的个数

操作系统 | 虚拟机及linux的安装

​ &#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《操作系统实验室》&#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 目录结构 1.操作系统实验之虚拟机及linux的安装 1.1 实验目的 1.2 实验内容 1.3 实验步骤 …

Linux常用命令——bzip2recover命令

在线Linux命令查询工具 bzip2recover 恢复被破坏的.bz2压缩包中的文件 补充说明 bzip2recover命令可用于恢复被破坏的“.bz2”压缩包中的文件。 bzip2是以区块的方式来压缩文件&#xff0c;每个区块视为独立的单位。因此&#xff0c;当某一区块损坏时&#xff0c;便可利用b…

【框架篇】统一异常处理

✅作者简介&#xff1a;大家好&#xff0c;我是小杨 &#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; 1&#xff0c;统一异常处理的介绍 统⼀异常处理使⽤的是 ControllerAdvice ExceptionHandler 来…

vue前端项目配置

目录 背景&#xff1a; 0.参考文档 0.1介绍 | Vue CLI (vuejs.org)&#xff08;官方文档&#xff09; 0.2【vue-cli5 bug】npm run build自动编译两次??? - 掘金 (juejin.cn) 0.3vendor.js文本过大 0.4vue性能优化 0.5启动项目一直是生产环境 0.6process.env&#x…

固定主机1500PLC与两台移动1200PLC之间以太网通讯

本方案搭建的是固定主机1500PLC与两台移动1200PLC之间以太网通讯。 无线通讯网络搭建 首先在固定端主机设备上的西门子S7-1500PLC上搭载一块达泰DTD418MB作为主站。然后在两台移动的西门子S7-1200PLC上分别搭载一块达泰DTD418MB作为从站。由此&#xff0c;便通过DTD418MB搭建…

Pandas教程(非常详细)(第五部分)

接着Pandas教程&#xff08;非常详细&#xff09;&#xff08;第四部分&#xff09;&#xff0c;继续讲述。 二十五、Pandas sample随机抽样 随机抽样&#xff0c;是统计学中常用的一种方法&#xff0c;它可以帮助我们从大量的数据中快速地构建出一组数据分析模型。在 Pandas…