Gradle入门:创建多项目构建

尽管我们只能使用一个模块来创建一个工作的应用程序,但是有时将我们的应用程序划分为多个较小的模块是比较明智​​的。

因为这是一个相当普遍的用例,所以每个自重的构建工具都必须支持它,Gradle也不例外。 如果Gradle项目具有多个模块,则称为多项目构建。

这篇博客文章描述了如何使用Gradle创建多项目构建。

让我们开始看一下Gradle构建的需求。

补充阅读:

如果您不熟悉Gradle, 则应先阅读以下博客文章,然后再继续阅读此博客文章:

  • Gradle入门:简介可帮助您安装Gradle,描述Gradle构建的基本概念,并描述如何使用Gradle插件向构建中添加功能。
  • Gradle入门:我们的第一个Java项目描述了如何使用Gradle创建Java项目并将应用程序打包到可执行jar文件中。
  • Gradle入门:依赖性管理介绍了如何管理Gradle项目的依赖性。

我们的Gradle构建要求

我们的示例应用程序具有两个模块:

  • 核心模块包含我们应用程序的其他模块所使用的通用组件。 在我们的例子中,它仅包含一个类: MessageService类返回字符串“ Hello World!”。 该模块只有一个依赖性:它具有一个使用Junit 4.11的单元测试。
  • app模块包含HelloWorld类,该类启动我们的应用程序,从MessageService对象获取消息,并将接收到的消息写入日志文件。 该模块具有两个依赖性:它需要核心模块,并使用Log4j 1.2.17作为日志记录库。

我们的Gradle版本还具有其他两个要求:

  • 我们必须能够使用Gradle运行我们的应用程序。
  • 我们必须能够创建不使用所谓的“胖罐”方法的可运行二进制分发。

如果您不知道如何使用Gradle运行应用程序并创建可运行的二进制发行版,
您应先阅读以下博客文章,然后再继续阅读此博客文章:

  • Gradle入门:创建二进制分发

让我们继续前进,了解如何创建满足我们要求的多项目构建。

创建多项目构建

我们的下一步是创建一个包含两个子项目的多项目Gradle构建: appcore 。 让我们从创建Gradle构建的目录结构开始。

创建目录结构

因为核心应用程序模块使用Java,所以它们都使用Java项目的默认项目布局 。 我们可以按照以下步骤创建正确的目录结构:

  1. 创建核心模块( core )的根目录,并创建以下子目录:
    • src / main / java目录包含核心模块的源代码。
    • src / test / java目录包含核心模块的单元测试。
  2. 创建应用程序模块( app )的根目录,并创建以下子目录:
    • src / main / java目录包含应用程序模块的源代码。
    • src / main / resources目录包含应用程序模块的资源。

现在,我们已经创建了所需的目录。 下一步是配置Gradle构建。 让我们从配置多项目构建中包含的项目开始。

配置我们的多项目构建中包含的项目

通过执行以下步骤,我们可以配置包含在多项目构建中的项目:

  1. settings.gradle文件创建到根项目的根目录。 多项目Gradle构建必须具有此文件,因为它指定了多项目构建中包含的项目。
  2. 确保应用程序核心项目包含在我们的多项目版本中。

我们的settings.gradle文件如下所示:

include 'app'
include 'core'

补充阅读:

  • Gradle用户指南:56.2设置文件
  • Gradle DSL参考:设置

让我们继续并配置核心项目。

配置核心项目

我们可以按照以下步骤配置核心项目:

  1. build.gradle文件创建到核心项目的根目录。
  2. 通过应用Java插件来创建Java项目。
  3. 确保核心项目从中央Maven2存储库获取其依赖项。
  4. 声明JUnit依赖关系(版本4.11)并使用testCompile配置。 此配置描述了核心项目在可以对其单元测试进行编译之前需要JUnit库。

核心项目的build.gradle文件如下所示:

apply plugin: 'java'repositories {mavenCentral()
}dependencies {testCompile 'junit:junit:4.11'
}

补充阅读:

  • Gradle入门:我们的第一个Java项目
  • Gradle入门:依赖管理

让我们继续并配置应用程序项目。

配置应用程序项目

在配置应用程序项目之前,我们必须快速浏览属于同一多项目构建的此类依赖项的依赖项管理。 这些依赖关系称为项目依赖关系。

如果我们的多项目构建具有项目A和B,并且项目B的编译需要项目A,则可以通过向项目B的build.gradle文件中添加以下依赖项声明来配置此依赖项:

dependencies {compile project(':A')
}

补充阅读:

  • Gradle用户指南:51.4.3。 项目依赖
  • Gradle用户指南:57.7。 项目库依赖项

现在,我们可以按照以下步骤配置应用程序项目:

  1. build.gradle文件创建到应用程序项目的根目录。
  2. 通过应用Java插件来创建Java项目。
  3. 确保应用程序项目从中央Maven2存储库获取其依赖项。
  4. 配置所需的依赖项。 该应用程序项目在编译时具有两个依赖关系:
    • Log4j(版本1.2.17)
    • 核心模块
  5. 创建一个可运行的二进制发行版 。

应用程序项目的build.gradle文件如下所示:

apply plugin: 'application'
apply plugin: 'java'repositories {mavenCentral()
}dependencies {compile 'log4j:log4j:1.2.17'compile project(':core')
}mainClassName = 'net.petrikainulainen.gradle.client.HelloWorld'task copyLicense {outputs.file new File("$buildDir/LICENSE")doLast {copy {from "LICENSE"into "$buildDir"}}
}applicationDistribution.from(copyLicense) {into ""
}

补充阅读:

  • Gradle入门:创建二进制分发

让我们继续并删除从核心应用程序项目的构建脚本中找到的重复配置。

删除重复的配置

当我们配置多项目构建的子项目时,我们向核心应用项目的构建脚本添加了重复的配置:

  • 因为两个项目都是Java项目,所以它们都应用Java插件。
  • 这两个项目都使用中央Maven 2存储库。

换句话说,两个构建脚本都包含以下配置:

apply plugin: 'java'repositories {mavenCentral()
}

让我们将此配置移到我们的根项目的build.gradle文件中。 在执行此操作之前,我们必须学习如何在根项目的build.gradle文件中配置子项目。

如果要将配置添加到名为core的单个子项目中,则必须将以下代码段添加到根项目的build.gradle文件中:

project(':core') {//Add core specific configuration here
}

换句话说,如果要将重复的配置移到根项目的构建脚本中,则必须将以下配置添加到其build.gradle文件中:

project(':app') {apply plugin: 'java'repositories {mavenCentral()}
}project(':core') {apply plugin: 'java'repositories {mavenCentral()}
}

这并不能真正改变我们的处境。 我们的构建脚本中仍然有重复的配置。 唯一的区别是,现在可以从根项目的build.gradle文件中找到重复的配置。 让我们消除这种重复的配置。

如果要向根项目的子项目添加通用配置,则必须将以下代码段添加到根项目的build.gradle文件中:

subprojects {//Add common configuration here
}

从根项目的build.gradle文件中删除重复的配置后,其外观如下:

subprojects {apply plugin: 'java'repositories {mavenCentral()}
}

如果我们拥有多项目构建中所有项目共享的配置,则应将以下代码段添加到
我们的根项目的build.gradle文件:

allprojects {//Add configuration here
}

补充阅读:

  • Gradle用户指南:57.1跨项目配置
  • Gradle用户指南:57.2子项目配置

现在,我们可以从子项目的构建脚本中删除重复的配置。 我们的子项目的新构建脚本如下所示:

core / build.gradle文件如下所示:

dependencies {testCompile 'junit:junit:4.11'
}

app / build.gradle文件如下所示:

apply plugin: 'application'dependencies {compile 'log4j:log4j:1.2.17'compile project(':core')
}mainClassName = 'net.petrikainulainen.gradle.client.HelloWorld'task copyLicense {outputs.file new File("$buildDir/LICENSE")doLast {copy {from "LICENSE"into "$buildDir"}}
}applicationDistribution.from(copyLicense) {into ""
}

现在,我们已经创建了一个多项目Gradle构建。 让我们找出我们刚刚做了什么。

我们只是做什么?

当我们在多项目构建的根目录中运行命令gradle projects时,我们将看到以下输出:

> gradle projects
:projects------------------------------------------------------------
Root project
------------------------------------------------------------Root project 'multi-project-build'
+--- Project ':app'
\--- Project ':core'To see a list of the tasks of a project, run gradle <project-path>:tasks
For example, try running gradle :app:tasksBUILD SUCCESSFUL

如我们所见,该命令列出了根项目的子项目( appcore )。 这意味着我们刚刚创建了一个具有两个子项目的多项目Gradle构建。

当我们在多项目构建的根目录中运行命令gradle任务时,我们看到以下输出(下面仅显示了相关部分):

> gradle tasks
:tasks------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------Application tasks
-----------------
distTar - Bundles the project as a JVM application with libs and OS specific scripts.
distZip - Bundles the project as a JVM application with libs and OS specific scripts.
installApp -Installs the project as a JVM application along with libs and OS specific scripts
run - Runs this project as a JVM application

如我们所见,我们可以使用Gradle运行我们的应用程序,并创建一个不使用所谓的“胖子”方法的二进制发行版。 这意味着我们已经满足了Gradle构建的所有要求。

附加信息:

  • Gradle用户指南:11.6。 获取有关构建的信息

让我们继续前进,找出从这篇博客文章中学到的知识。

摘要

这篇博客文章教会了我们三件事:

  • 多项目构建必须在根项目的根目录中具有settings.gradle文件,因为它指定了多项目构建中包含的项目。
  • 如果必须在多项目构建的所有项目中添加通用配置或行为,则应将此配置(使用allprojects )添加到根项目的build.gradle文件中。
  • 如果必须在根项目的子项目中添加通用配置或行为,则应将此配置(使用subprojects )添加到根项目的build.gradle文件中。

PS:您可以从Github获得此博客文章的示例应用程序 。

翻译自: https://www.javacodegeeks.com/2015/01/getting-started-with-gradle-creating-a-multi-project-build.html

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

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

相关文章

float

1.float元素有继承属性&#xff1a;inherit. 2. span{width:100px;height:100px;background:red; } 文档中不显示&#xff0c;因为span为块状元素&#xff0c;不能设置宽和高。 3. span{width:100px;height:100px;background:red;float&#xff1a;left&#xff1b; } 此时在文…

[转载]Buffon投针实验:究竟为什么是pi?

Buffon投针实验&#xff1a;究竟为什么是pi&#xff1f; Brain Storm | 2009-11-06 20:16| 57 Comments | 本文内容遵从CC版权协议 转载请注明出自matrix67.com数学学习真正悲哀的就是&#xff0c;记住了某个神奇而伟大的定理&#xff0c;看懂了其最严密的推导过程&#xff0c;…

EE Servlet 3:使用会话和过滤器开发用户登录

我在上一篇文章中介绍了Application类&#xff0c;您可以在其中设置后端服务。 我添加的一个示例服务是UserService 。 该服务将加载包含用户名和密码集的Java用户属性文件&#xff1b; 稍后将用于对用户进行身份验证以登录到Web应用程序。 现在&#xff0c;我将展示如何使用标…

Ajax应用查询员工信息

首先要用上一篇的步骤启动服务器&#xff0c;建立站点。然后在该站点下创建php文件和html文件。 php代码如下&#xff0c;文件名为server.php <?php //设置页面内容是html编码格式是utf-8 header("Content-Type: text/plain;charsetutf-8"); //header("Co…

局域网基础知识

一、局域网的特征&#xff1a;   局域网分布范围小&#xff0c;投资少&#xff0c;配置简单等&#xff0c;具有如下特征&#xff1a;     1&#xff0e;传输速率高&#xff1a;一般为1Mbps--20Mbps&#xff0c;光纤高速网可达100Mbps&#xff0c;1000MbpS     2&…

初始化懒惰关系以及何时使用它们的5种方法

实体之间关系的延迟加载是JPA中公认的最佳实践。 它的主要目标是仅从数据库中检索请求的实体&#xff0c;并仅在需要时加载相关实体。 如果我们只需要请求的实体&#xff0c;那是一个很好的方法。 但是&#xff0c;如果我们还需要一些相关实体&#xff0c;它会增加工作量&#…

fieldset ----- 不常用的HTML标签

fieldset 元素可将表单内的相关元素分组。 <fieldset> 标签将表单内容的一部分打包&#xff0c;生成一组相关表单的字段。 当一组表单元素放到 <fieldset> 标签内时&#xff0c;浏览器会以特殊方式来显示它们&#xff0c;它们可能有特殊的边界、3D 效果&#xff…

谷歌移动应用强调设计元素:向极简风格转型

导语&#xff1a;美国科技博客TechCrunch今天撰文称&#xff0c;一向不看重设计的谷歌&#xff0c;最近也开始在移动应用中强调设计元素&#xff0c;并向极简风格转型。 以下为文章全文&#xff1a; 谷歌的设计向来不够酷&#xff0c;Gmail和Google Docs的功能都很不错&#xf…

Java 8流和Lambda表达式–解析文件示例

最近&#xff0c;我想从输出日志中提取某些数据。 这是日志文件的一部分&#xff1a; 2015-01-06 11:33:03 b.s.d.task [INFO] Emitting: eVentToRequestsBolt __ack_ack [-6722594615019711369 -1335723027906100557] 2015-01-06 11:33:03 c.s.p.d.PackagesProvider [INFO] -…

使用入站适配器公开HTTP Restful API。 第1部分(XML)

1.简介 这篇文章的目的是使用Spring Integration HTTP入站适配器实现HTTP Restful API。 本教程分为两个部分&#xff1a; XML配置示例&#xff08;同一篇文章&#xff09;。 Java DSL示例。 这将在本教程的下一部分中进行说明&#xff0c;展示如何使用Spring Integration Ja…

根据thickbox定制自己的遮罩层

Jquery有很多遮罩层插件&#xff0c;我使用了一款叫做thickbox的插件&#xff0c;效果很好。 但现在我要和后台交互&#xff0c;后台处理数据时间较长&#xff0c;为了提示用户&#xff0c;同时不让用户进行其他操作&#xff0c;这时候thickbox就不适用了&#xff0c;因为它允许…

Es6学习笔记(7)----数组的扩展

参考书《ECMAScript 6入门》http://es6.ruanyifeng.com/数组的扩展1.扩展运算符:可以将数组转化成逗号隔离的单个参数...[1,2,3] //控制台运行报错console.log(...[1,2,3]);//1,2,3(1)代替apply方法function test(a,b){return a b;}test.apply(null,[1,2]) 同 test(...[1,2]) 作…

使用jOOQ和JavaFX将SQL数据转换为图表

最近&#xff0c;我们已经展示了Java 8和函数式编程将如何为使用jOOQ和Java 8 lambda和Streams进行SQL数据的函数数据转换为Java开发人员带来新的视角。 今天&#xff0c;我们将这一步骤更进一步&#xff0c;将数据转换为JavaFX XYChart.Series以根据数据生成美观的条形图。 设…

有一只猪400斤,桥承重200斤,怎么过桥?

条件:1 猪是活猪,任何方案都不 能切割猪。2 故事发生在猪王国&#xff0c;不要引 入人的因素。3 是过桥&#xff0c;不是过河&#xff0c;不要 说游泳过去。4 是过桥&#xff0c;不是过涧&#xff0c;不要 说飞过去。5 桥是承重200斤的桥&#xff0c;把桥 挪到平地上抑或过另一…

node.js学习笔记(1)

一&#xff0e; 安装以及环境配置 安装路径 http://nodejs.cn/download/ 多种环境选择 环境变量的配置 Step1 先检查环境变量中的系统变量里面的path,查看是否加入了node.js 例如我的node.js安装路径是C:\Program Files\nodejs 那么&#xff0c;这个path里面就应该加…

do语句转化为局部函数一例

do: (do ((x a (b x)) (y c (d y))) ((test x y) (z x y)) (f x y)) 局部函数&#xff1a; (labels ((rec (x y) (cond ((test x y) (z x y)) (t (f x y) (rec (b x) (d y)))))) …

主要版本发布后Java开发人员应使用的15种工具

新部署的生存工具包&#xff1a;适用于Java开发人员的工具&#xff0c;这些工具经常将代码部署到生产中&#xff01; Takipi会检测生产中的所有错误&#xff0c;并像发生错误时一样显示变量值 立即部署并获得免费的T恤 适用于新部署的终极生存套件 与在僵尸末日场景下玩弄&…

js dom node.children与node.childNodes区别

不同点&#xff1a;node.children不会取到节点下面的TextNode但是node.childNodes会取到 共同点&#xff1a;两者都是集合类数组&#xff0c;可以通过索引的方式取到值也可以用for循环遍历 更多专业前端知识&#xff0c;请上 【猿2048】www.mk2048.com

Java EE 7批处理和魔兽世界–第2部分

今天&#xff0c;我将把第二部分带到我以前关于Java EE 7批处理和《魔兽世界–第1部分》的帖子中。 在本文中&#xff0c;我们将了解如何从第1部分中获得的数据中汇总和提取指标。 概括 批处理目的是下载魔兽世界拍卖行的数据&#xff0c;处理拍卖并提取指标。 这些指标将建立…

js导航条 二级滑动 模仿块级作用域

for(var i 1;i<7;i){    //因为首级标题有6个&#xff0c;对每个首级标题添加mouseover和mouseout事件。    //这里用到块级作用域(function(k){document.getElementById("p_"k).addEventListener(mouseover,function(event){document.getElementById(p_…