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

news2024/11/18 17:53:57

目录

  • 【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都会产生影响

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

API 集成测试工具Hitchhiker 0.1.1 正式发布

Hitchhiker 是一款开源的 Restful Api 集成测试工具,你可以在轻松部署到本地,和你的 team 成员一起管理 Api。 能做什么 * Team 协作开发 Api * Api 历史修改记录及支持 diff 展示 * 支持多环境变量及运行时变量 * 支持 Schedule 及批量 run * 不同…

Ubuntu诞生已经19年了

导读2004 年 10 月 20 日,Ubuntu 4.10 正式发布,代号‘Warty Warthog’。 2004 年 10 月 20 日,Ubuntu 4.10 正式发布,代号‘Warty Warthog’。 ▲ Ubuntu 4.10 与最新版 Ubuntu 23.10 的对比 作为 Ubuntu 第一个版本&#xff0…

[mysql]索引优化-2

目录 一、分页查询优化1.根据自增且连续的主键排序的分页查询2.根据非主键字段排序的分页查询 二、Join关联查询优化1.嵌套循环连接 Nested-Loop Join(NLJ) 算法2.基于块的嵌套循环连接 Block Nested-Loop Join(BNL)算法 三、count(*)查询优化1.查询mysql自己维护的总行数2.sho…

PySide/PYQT如何用Qt Designer和代码来设置文字属性,如何设置文字颜色?

文章目录 📖 介绍 📖🏡 环境 🏡📒 实现方法 📒📝 Qt Designer设置📝 代码📖 介绍 📖 本人介绍如何使用Qt Designer/代码来设置字体属性(包含字体颜色) 🏡 环境 🏡 本文使用Pyside6来进行演示📒 实现方法 📒 📝 Qt Designer设置 首先打开Qt De…

Langchain-Chatchat环境安装

目录 一、简介 二、环境安装 三、使用Langchain-Chatchat 3.1、下载模型 3.2、设置配置文件 3.3、执行 一、简介 基于 ChatGLM 等大语言模型与 Langchain 等应用框架实现,开源、可离线部署的检索增强生成(RAG)大模型知识库项目。 🤖️ 一种利用 l…

通用结构化剪枝DepGraph

文章目录 0. 前言一. 第一部分: Torch-Pruning1.1 传统的剪枝流程 - ResNet-18结构化剪枝1.2 Torch-Pruning剪枝 - ResNet-18结构化剪枝1.3 Torch-Pruning剪枝 - 遍历所有分组1.4 Torch-Pruning剪枝 - 剪枝器 High-level Pruners1.5 Torch-Pruning剪枝 - 拓展到更复杂的神经网…

中国电子学会2023年09月份青少年软件编程Python等级考试试卷六级真题(含答案)

2023-09 Python六级真题 分数:100 题数:38 测试时长:60min 一、单选题(共25题,共50分) 1. 以下选项中,不是tkinter变量类型的是?(D )(2分) A.IntVar() B.StringVar() C.Do…

高效简洁的文档翻译网站

一款简单而强大的文档翻译网站 一款文字/文件翻译的网站,支持多个领域的翻译,支持常见的语言翻译(韩/日/法/英/俄/德…),最大百分比的保持原文排版(及个别除外基本100%还原)。 新用户注册就有100页的免费额度,每月系统还会随机赠送翻译额度,…

ssh开启,centOS7

1、先确定虚拟机是否装了openssh-server,执行 yum list installed |grep openssh-server 查看是否安装 [rootlocalhost ~]# yum list installed |grep openssh-server Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast openssh-serve…

C语言--每日五道选择题--Day9

第一题 1、如下程序的运行结果是( ) char c[5]{a, b, \0, c, \0}; printf("%s", c); A: a b B: ab\0c\0 C: ab c D: ab 答案及解析 D 首先这是一个字符数组,我们要知道无论是字符串还是字符数组,它们遇到ASCII值为0就…

第6 章 布局管理及多窗口技术

6.1 控件布局技术 所谓GUI界面,归根结底,就是一堆可视化控件的叠加。创建一个窗口,把按钮放上面,把图标放上面,这样就成了一个界面。在放置时,控件的位置尤为重要。我们必须指定控件放在哪里,以…

vue3项目常用功能分享

Vue3常用功能分享 本文主要分享一下在使用vue3开发项目时的一些常用功能 一、自动注册全局组件 自动注册components目录下所有vue组件并以组件的文件名为组件的名称 // components/index.tsimport { type App, defineAsyncComponent } from vue const components Object.e…

Leetcode—剑指OfferII LCR 019.验证回文串II【简单】

2023每日刷题&#xff08;二十七&#xff09; Leetcode—剑指OfferII LCR 019.验证回文串II 实现代码 class Solution { public:bool judgeFunc(string s, int left, int right) {while(left < right) {if(s[left] ! s[right]) {return false;}left;right--;}return true;…

【数据结构】拓扑序列求法

概念不多说了&#xff0c;有疑问的搜一下&#xff0c;这里直接放求法&#xff1a; 找到入度为0的节点输出并删除该节点&#xff0c;并删除与该点链接的边重复第一步 例子 输出a&#xff0c;删除a输出b&#xff0c;删除b输出c&#xff0c;删除c 最终结果为abcdef 注意 拓扑排…

WorkPlus IM即时通讯软件:私有化部署、安全加密、信创适配

WorkPlus IM即时通讯软件是一款具备私有化部署、安全加密和信创适配功能的高效沟通工具。下面我们将详细介绍WorkPlus IM的功能和特点。 WorkPlus支持私有化部署&#xff0c;这意味着企业可以完全掌控数据的存储与传输。企业可以选择将该软件部署在自己的本地服务器上&#xff…

文件上传 [ACTF2020 新生赛]Upload1

打开题目&#xff0c;发现是一道文件上传题目 随便上传个一句话木马上去 发现网站前端有白名单限制&#xff0c;只能上传含有jpg&#xff0c;png&#xff0c;gif的后缀文件 最开始我想到的做法是先上传htaccess文件&#xff0c;bp修改文件头&#xff0c;上传成功后然后再上传以…

Linux文件缓冲区

文章目录 1. 缓冲区现象2. 用户级和系统级缓冲区3. 缓冲区刷新4. 为什么要有缓冲区5. 文件打印的全缓冲6. 模拟实现C语言文件标准库 本章gitee代码仓库&#xff1a;重定向、模拟C语言文件标准库 1. 缓冲区现象 我们这里分别调用了4个差不多的函数&#xff0c;但是结果是有一定差…

Sprint Boot 学习路线 5

Spring MVC Spring MVC是Spring框架的一部分&#xff0c;是一个Web应用程序框架。它旨在使用Model-View-Controller&#xff08;MVC&#xff09;设计模式轻松构建Web应用程序。 在Spring MVC中&#xff0c;应用程序被分为三个主要组件&#xff1a;Model、View和Controller。M…

深入理解强化学习——多臂赌博机:知识总结

分类目录&#xff1a;《深入理解强化学习》总目录 我们在《深入理解强化学习——多臂赌博机》系列文章中介绍了几种平衡试探和开发的简单方法。 ϵ − \epsilon- ϵ−贪心方法在一小段时间内进行随机的动作选择&#xff0c;而UCB方法虽然采用确定的动作选择&#xff0c;却可以通…