一,模块化的原因及意义
模块化是一种将大型的软件系统拆分成相互独立的模块的方法。具有以下优势:
- 代码复用:不同的模块可以共享相同的代码。这样可以避免重复编写相同的代码,提高开发效率。
- 模块独立性:每个模块都可以独立构建、测试和部署。这样可以降低整个项目的维护成本,例如当有一个模块需要更新时,只需要重新构建该模块而不会影响其他模块。
- 模块化开发:开发人员可以专注于某个特定的模块,而不需要关心整个项目的复杂性。这样可以提高开发效率和代码质量。
- 可扩展性:通过定义模块之间的依赖关系,可以方便地引入和管理第三方库和框架。这样可以提高项目的灵活性和可扩展性。
JDK从9版本开始,也对基础类库进行了模块化
二、Gradle介绍
Gradle是一个基于JVM(不止java)的构建工具,用于自动化构建、测试、部署和发布软件项目。它支持多种编程语言,包括Java、Groovy和Kotlin,并且可以与各种开发工具和持续集成系统集成。
相比于老前辈maven,gradle的使用率可就没那么广泛了。maven依然是主导,gradle最大的用户还是Android平台,在其他领域运用依然很少。在java平台,Gradle最著名的项目非spring/springboot莫属了。
2.1Gradle后发优势
相比于maven,gradle具有以下优势:
- 灵活性:代码即脚本,可以直接使用Groovy或Kotlin编写脚本,而Maven则需要转化为xml格式的插件,非常麻烦。
- 性能:Gradle具有更好的构建性能。它使用增量编译和缓存机制,只重新构建有变更的部分,从而提高构建速度。而Maven则没有这样的机制,每次都会重新编译所有文件。这尤其在大型项目中能够显著减少构建时间。
-
可读性:Gradle的构建脚本更易读和维护。它使用了一种声明性的语法,能够更清晰地表达构建逻辑和依赖关系。而Maven的XML格式相对较冗长和繁琐,不太直观。
2.2Gradle的劣势
有优势就肯定有劣势,如果gradle全面领先的话,那还有maven什么事呢?gradle存在以下劣势:
- 学习曲线:相较于Maven,Gradle的学习曲线较陡峭。由于Gradle提供了更灵活的构建脚本语法和更强大的插件系统,初学者可能需要花费一些时间来熟悉和理解Gradle的概念和用法。主要是比较难入门,让很多人从入门到放弃。
- 文档和社区支持:相较于Maven,Gradle的生态支持相对较少。由于Maven出道早,运用广泛,在文档和社区方面更为成熟和丰富。
前一篇文章《Maven模块化最佳实践》介绍了如何使用maven进行模块化开发,本文继续讲述如何使用gradle进行模块化开发。
三,模块化的继承效果
在Gradle中,继承指的是使用父项目定义的配置信息来为子项目提供默认的配置。这种继承关系可以帮助开发者减少重复的配置,并确保子项目与父项目保持一致的构建方式。子模块可以继承的有以下内容
- 配置
- 依赖声明
- 插件声明
3.1继承配置
在Gradle中,继承属性是指子项目可以继承父项目中定义的属性值,也可以重新覆盖父项目的同名参数。
在实践中,我们可以把所有子模块需要的依赖版本,编译参数等配置统一放到父模块进行声明。这样,便于查阅与修改。例如mmorpg-parent的builder.setting配置
ext {
nettyVersion = "4.1.33.Final"
minaVersion = "2.0.7"
springBootVersion = '2.6.0'
gsonVersion = "2.8.0"
mysqlVersion = "5.1.6"
jacksonVersion = "2.12.1"
protostuffVersion = "1.5.9"
protobufVersion = "1.11.7"
}
3.2继承依赖
继承依赖是指子项目可以继承父项目中定义的依赖管理。这样可以简化子项目的依赖配置,避免重复定义和维护。
3.2.1统一申明子模块的依赖,避免子模块直接依赖冲突。
dependencies {
api ("org.springframework.boot:spring-boot-dependencies:${springBootVersion}")
api 'org.apache.commons:commons-lang3:3.4'
compileOnly 'org.projectlombok:lombok:1.18.6'
annotationProcessor 'org.projectlombok:lombok:1.18.6'
implementation ("com.google.code.gson:gson:${gsonVersion}")
implementation ("io.netty:netty-all:${nettyVersion}")
}
3.2.2子模块统一模块
父模块可以把子模块都需要的依赖都统一进行申明,这样,子依赖即使没有显示引入,都会被动全部拥有,这样可以减少配置。典型的这些依赖有junit,sl4f等等。如mmorpg项目的父模块申明
subprojects {
dependencies {
testImplementation ("junit:junit:${junitVersion}")
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
}
}
3.3继承任务(task)
maven通过插件(plugin)来构建项目命令,而gradle通过任务(task)。task直接用脚本语言书写,不用封装,非常灵活。
maven的插件继承,子模块可以使用并覆写某些配置。而gradle的task继承更像OOP,子模块可以在子任务中使用父任务的属性和方法,例如通过super
关键字来调用父任务的方法。使用如下:
1.在build.gradle文件中定义一个父任务(例如,名为parentTask),并为其添加所需的配置和行为。例如:
task parentTask {
// 添加父任务的配置和行为
doLast {
println 'This is the parent task'
}
}
2.在build.gradle文件中定义一个子任务(例如,名为childTask),并使用extends关键字继承父任务。例如:
task childTask(type: parentTask) {
// 添加子任务的配置和行为
doLast {
println 'This is the child task'
}
}
四、模块化的聚合效果
在Gradle中,聚合是指将多个子项目合并为一个大项目进行构建。聚合可以帮助您管理包含多个相关项目的大型代码库。以下是如何在Gradle中进行聚合的步骤:
创建一个父项目文件夹,并在该文件夹下创建一个settings.gradle文件。添加需要聚合的子模块,例如mmorpg的配置
rootProject.name = 'mmorpg'
include 'game-common', 'game-protocol', 'game-net', 'game-data-starter',
'game-server','game-mq', 'game-rpc'
在父项目文件夹中运行Gradle命令,例如gradle build
。Gradle将会自动聚合并构建父项目及其所有子项目。
五、重命名子模块的脚本名称
maven使用pom.xml来构建管理任务,不管是父模块还是子模块,都是一样的名字,这样在查找文件的时候不够方便。而Gradle则运行给子模块重命名。在setting.gradle下输入以下命令
// 修改子项目的build文件名,重名很难查找
rootProject.children.each {
it.buildFileName = it.name - "game-" + ".gradle"
}
每个子模块独立名字