Gradle 多模块
如果你十分熟悉 Gradle
的使用,可能你会觉得我接下来要讲的内容很蠢。因为对于 Gradle
来讲,一个多模块项目的构建是非常非常简单的。
但是对于当时第一次接触到Gradle的我来讲,这个问题也折磨了我一段时间。这篇文章作为存货已经囤积很久了,我想也是时候拿出来水一水更新了。
模块配置
对于一个基础的 Gradle
项目来讲,它的结构大概是这样的:
由于我是使用 Gradle Kotlin DSL 的,所以你会发现配置脚本的结尾都会有个
.kts
。
root
├── src
│ ├─ main/java
│ ├─ main/resources
│ ├─ test/java
│ └─ test/resources
│
├── build.gradle.kts
├── gradle.properties
└── settings.gradle.kts
这时候,如果我想要将其配置为一个多模块的项目,比如变成如下结构:
root
├── overtime-common ----> 第一个模块
│ └── src
│ ├─ main/java
│ ├─ main/resources
│ ├─ test/java
│ └─ test/resources
│
├── overtime-app -------> 第二个模块
│ └── src
│ ├─ main/java
│ ├─ main/resources
│ ├─ test/java
│ └─ test/resources
├── build.gradle.kts
├── gradle.properties
└── settings.gradle.kts
其实这是很简单的,你只需要在 settings.gradle.kts
这么配置:
include("overtime-common")
include("overtime-app")
或者说直接一步到位:
include("overtime-common", "overtime-app")
这就代表将项目中的 overtime-common
、overtime-app
作为子项目加载进来。很容易不是么?
那么我们继续往下看,现在假设我希望我的项目是这样的:
root
├── commons
│ ├── common-core -------> 子模块
│ ├── common-domain -------> 子模块
│ ├── common-application -------> 子模块
│ └── common-repository -------> 子模块
│
├── services
│ ├── user
│ │ ├── user-domain ----> 子模块
│ │ ├── user-api ----> 子模块
│ │ ├── user-repository ----> 子模块
│ │ ├── user-service ----> 子模块
│ │ ├── user-service-impl ----> 子模块
│ │ ├── user-controller ----> 子模块
│ │ └── user-application ----> 子模块
│ │
│ ├── compensate
│ │ ├── compensate-domain ----> 子模块
│ │ ├── compensate-api ----> 子模块
│ │ ├── compensate-repository ----> 子模块
│ │ ├── compensate-service ----> 子模块
│ │ ├── compensate-service-impl ----> 子模块
│ │ ├── compensate-controller ----> 子模块
│ │ └── compensate-application ----> 子模块
│ │
│ │
│ └── 其他...
│
├── build.gradle.kts
├── gradle.properties
└── settings.gradle.kts
简单来说,我希望能有一个存放所有公共模块的 overtime-common
父模块,来统一配置所有的"公共模块";
我还希望能有一个存放所有实际业务服务模块的 services
父模块,来统一配置所有的服务模块。
而对于服务模块来讲,每个不同的服务都会有那么固定的7个小的子模块来细分模块之间的职责,比如 -api
模块为 -controller
提供约束、-service
为 -service-impl
提供约束等等。
当时我的脑海中想到这个问题的时候,第一反应是去查了查"如何配置Gradle多模块" 或者 "Gradle 嵌套模块",因为基于我对于 Maven
的认知,在 Maven
中,每个模块的每个子模块都需要配置它对应的父模块,且父模块也要配置其下的所有子模块。当时的我认为,Gradle也许也许要类似的配置。
然而查询的结果显而易见,我并没有找到我想要的答案。直到我查询了 Gradle
的官方文档才恍然大悟:
include("overtime-commons:common-core")
include("overtime-commons:common-domain")
include("overtime-commons:common-application")
include("overtime-commons:common-repository")
include("services:user:user-domain")
include("services:user:user-api")
include("services:user:user-repository")
include("services:user:user-service")
// 以及其他...
实际上,只需要通过 :
代替路径中的 /
, 按照从根项目开始的路径将他们添加进去即可。当我第一次尝试出这样的结果后不由得轻声感叹,并在心里默默的指责了一声给我留下了刻板印象的Maven。
但是你会发现,如果真的这么写,如果项目变多了,你要写的 include
也是会非常多的。比如现在我这个项目中,光 service
下的服务模块就有4个,每个模块都算上那7个小模块的话,就要有28个模块了。
但是幸运的是,gradle的配置是以脚本的方式进行配置的,你可以很轻松的去做一些"特别的"事情,比如这样:
includeServices("user")
includeServices("compensate")
// 其他...
val modules = listOf(
"domain", "repository",
"service", "service-impl",
"api", "controller", "application"
)
fun Settings.includeServices(name: String) {
modules.forEach { module ->
include("services:$name:$name-$module")
}
}
你可以通过自定义一些函数来轻松的做到一些xml做不到的事情,可谓是十分便利了。
通过上面这个方式,只需要一个 includeServices
就可以一次性增加对应模块下的7个相关的子模块了,妙哉妙哉~