Gradle 是一个基于 Ant 和 Maven 概念建立的项目自动化构建工具,使用基于 Groovy 和 Kotlin 的 DSL 语言来声明项目构建配置。相比于 Maven 使用 XML 进行项目构建配置,要简单很多。Gradle 对于多项目的构建支持非常优秀,配置十分简单,在进行多个项目协作时非常容易。Gradle 没有建设自己的仓库系统,而是选择直接使用目前已有的 Maven 仓库系统,这使得从 Maven 向 Gradle 过渡变得十分容易。
Wrapper 模式
大部分的工具需要安装以后使用,但 Gradle 支持在项目中采用 Wrapper 模式使用。Wrapper 模式可以在不同的开发设备之间同步相同的 Gradle 版本及配置,避免因为安装不同版本的 Gradle 造成构建失败的情况。
Gradle Wrapper 是针对项目存在的,在每个项目中由六个文件和一个文件夹组成:
gradlew,Unix 可执行文件;gradlew.bat,Windows 批处理文件;build.gradle,构建脚本;如果采用 Kotlin DSL,该文件名称为build.gradle.kts;settings.gradle,工程名称指定文件;如果采用 Kotlin DSL,该文件名称为settings.gradle.kts;gradle/wrapper/gradle-wrapper.jar,Wrapper JAR 文件;gradle/wrapper/gradle-wrapper.properties,Wrapper 配置文件,通常用于指定 Gradle 版本号。
在项目中,可以根据操作系统的不同来通过 Wrapper 运行相应的 Gradle 任务:
- Unix 系统:
./gradlew <task>; - Windows 系统:
gradlew <task>。
所有的 Wrapper 组成文件需要放置进入版本库,以在各个开发设备之间保持同步。
可以通过 gradle wrapper --gradle-version <版本号> --gradle-distribution-url <下载链接> --distribution-type=(bin|all) 来向现有的项目添加 Gradle Wrapper。如果未指定 Gradle 的版本,则会使用当前机器中安装的版本建立 Wrapper。指定的 Gradle 可执行文件位于 $USER_HOME/.gradle/wrapper/dists,如果网络下载太慢,可以直接使用下载工具下载相应的包后,覆盖这其中的文件以完成安装,或者指定下载链接进行加速。下载链接还可以通过编辑 gradle/wrapper/gradle-wrapper.properties 中的 distributionUrl 一项来进行配置。
常用命令行命令
gradle init,建立一个新的 Gradle 构建。gradle -q projects,列举全部项目及子项目。gradle -q tasks,列举全部可用 task。gradle -q dependencies,列举项目依赖。gradle -q sub-project-name:dependencies,列举指定子项目依赖。gradle <task>,执行指定 task。gradle :projectName:taskName,执行指定项目中的 task。
在项目根目录中时,将命令 gradle 替换成 gradlew ,可以用 Wrapper 模式中的 Gradle 代替全局 Gradle。
使用 Plugin
在构建配置中使用 plugin 需要声明,格式为 plugins { id 'plugin id' version 'plugin version' [apply 'false'] } ,见以下示例。
plugins {id 'java'id 'com.jfrog.bintray' version '0.4.1'}
声明 plugin 将同时解决依赖并应用 plugin,所以其使用方式有一定的限制。其不能在 if 等语句中使用,必须在顶级脚本部分使用。所以在大部分情况下传统语法更加实用。
常用 Plugin
部分 Plugin 需要在 buildscript { } 中定义依赖,下表中所描述依赖需要添加到 buildscript { } 的 dependencies { } 中。
- Plugin ID:
java,用于支持 Java 语言,并打包项目为 Jar。 - Plugin ID:
groovy,用于支持 Groovy 语言,继承自 Java。 - Plugin ID:
scala,用于支持 Scala 语言,继承自 Java。 - Plugin ID:
java-library,支持将应用打包为 Jar 库。 - Plugin ID:
application,支持将应用打包为命令行应用。 - Plugin ID:
ear,支持将项目打包为 J2EE 应用。 - Plugin ID:
war,支持将项目打包为 Web 应用。 - Plugin ID:
eclipse,支持生成 Eclipse 所使用的文件。 - Plugin ID:
idea,支持生成 IntelliJ IDEA 所使用的文件。 - Plugin ID:
signing,支持对生成的文件进行签名。 - Plugin ID:
maven-publish,支持发布到 Maven 远程仓库。 - Plugin ID:
org.jetbrain.kotlin.jvm,支持 Kotlin 语言,需要添加依赖org.jetbrains.kotlin:kotlin-gradle-plugin。 - Plugin ID:
org.springframework.boot,为项目增加 Spring Boot 环境, - Plugin ID:
io.spring.dependency-management,为 Spring Boot 项目提供类似于 Maven 的依赖版本管理。
使用 Kotlin 的附加内容
使用 Kotlin 语言时,单纯使用 Plugin 指定 Kotlin 语言环境并不能完成 Kotlin 语言环境的配置,其 build.gradle 的 dependencies { } 中还需要加入以下内容的配置:
dependencies {
// 默认版本的标准库用于支持 Java 6
implementation "org.jetbrains.kotlin:kotlin-stdlib"
// 如果使用更高版本的 Java 特性,可以使用扩展版本的标准库
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.jetbrains.kotlin:kotlin-reflect"
testImplementation "org.jetbrains.kotlin:kotlin-test"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
}
其需要引入的版本可在 buildscript 的 ext 中进行定义,具体定义方法见后文。
当使用 Kotlin 时,其 main 函数为一个顶级函数,不必在一个类中声明,这时书写 mainClassName 时可以以 main 函数所在的文件作为类名,例如 main 函数所在文件为 com/example/Start.kt,则 mainClassName 值为 com.example.StartKt。
使用 Spring Boot 的附加内容
使用 io.spring.dependency-management Plugin 可以使得在书写项目的依赖项时不必声明版本号,这个 Plugin 会自动进行版本的管理。如果需要自定义版本号,则需要在 ext { } 部分对相应的依赖项的版本号进行声明,依赖项的名称可参考 Spring Dependency Management BOM。
如果不使用 Plugin 的方式使用 Dependency Management 功能,则需要在 build.gradle 的 dependencyManagement { } 中按照以下示例引入 BOM。
dependencyManagement {
import {
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
// 如果是使用Spring Cloud可以引入以下BOM,其中springCloudVersion在ext { }中定义
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
声明依赖项
声明依赖库
依赖库使用 repositories { } 进行声明,每条语句声明一个依赖库,Gradle 查询依赖按照声明顺序进行查询。常用的声明语句有:
mavenCentral(),使用 Maven 中央库。jcenter(),使用 JCenter 库。maven { url "URL" },使用指定 URL的Maven 库。ivy { url "URL" },使用指定 URL 的 Ivy 库。flatDir { dirs "path" },使用本地目录中的库。
常用依赖库
| 依赖库 | 类型 | URL或定义 |
|---|---|---|
| Maven Central | Maven | mavenCentral() |
| Bintray JCenter | Maven | jcenter() |
| Google Android | Maven | google() |
| 阿里云Maven镜像 | Maven | http://maven.aliyun.com/nexus/content/groups/public/ |
声明项目依赖
项目依赖使用 dependencies { } 进行声明,每条语句声明一个依赖项,Gradle会根据依赖项进行递归依赖获取。常用的声明格式有两种: group: 'group-name', name: 'artifact-name', version: 'artifact-version' 的分散声明格式和 'group-name:artifact-name:artfact-version'的短格式,两种格式内容一致,可根据需要选择使用。
对本地库文件的依赖可以使用 files 或者 fileTree 进行引用,例如 runtime files('libs/a.jar') 或者 runtime fileTree(dir: 'libs', include: '*.jar')。
如果需要对其他兄弟项目进行依赖,则可以使用 project 进行引用,例如 runtime project(':shared:api')。
多项目构建
Gradle可以使用 settings.gradle 和 build.gradle 两个文件来进行多项目构建。其中 settings.gradle 与 build.gradle 需要放置于根项目或者主项目路径下;子项目路径下可以根据需要放置这两个文件,或其一,或不使用。
settings.gradle 中可以使用 include 来声明当前项目对于其他项目的包含,如果根项目中声明包含了所有的子项目,则执行 gradle build 时就会将根项目连同子项目一起打为一个包。所以如果根项目只是为子项目提供一个可共享开发环境,则只需要在子项目中建立 settings.gradle 来定义子项目之间的包含即可。
多项目间依赖
Gradle 的依赖是存在依赖传递的,在进行多项目间依赖时,需要注意 jar 包重复的问题。
平级项目间依赖
平级项目间的目录关系可以见下图所示。
假设目前项目 B 与项目 C 均需要依赖项目 A,且项目 C 还需要依赖项目 B,则可以在项目 B 与项目 C 中建立 settings.gradle 文件来定义项目依赖。
项目 B 中的 settings.gradle:
rootProject.name='B'
includeFlat 'A'
项目 B 中的 builg.gradle:
dependencies {
compile project(':A')
}
项目 C 中的 settings.gradle:
rootProject.name='C'
includeFlat 'A', 'B'
项目 C 中的 build.gradle:
dependencies {
compile project(':A')
compile project(':B')
}
聚合项目间依赖
当项目过大过复杂,或者需要向外提供 API 时,就需要使用到聚合项目,这个项目中会包含若干小项目作为其模块。聚合项目的目录关系可以见下图所示。
项目 A 包含了两个子项目 A1 和 A2,这时项目 A 中可以添加 settings.gradle 来声明项目聚合。
项目 A 的 settings.gradle:
rootProject.name='A'
include 'A1', 'A2'
项目 A 中不需要在 build.gradle 中使用 dependencies 声明依赖,但项目 A1 与 A2 中需要使用 build.gradle 来定义其项目详细。
注意,在项目 A1 和 A2 的级别中,放置
settings.gradle文件是不会起作用的,项目 A1 和 A2 如果需要依赖其他项目,需要在项目A的settings.gradle中定义,具体见下一节的交叉依赖。
项目交叉依赖
在一个项目群(微服务中常见)中,各个项目之间经常存在交叉依赖的情况,这是最复杂的依赖状态。例如有如下图所示的项目目录关系。
项目 C1 对于项目 A1 存在依赖,这时就需要在项目 C 的 settings.gradle 中声明项目间的依赖。
项目 C 的 settings.gradle:
rootProject.name='C'
include 'C1'
includeFlat 'A'
include 'A:A1'
此时需要在项目 C1 的 build.gradle 中添加对于项目A1的依赖:
dependencies {
compile project(':A:A1')
}
同理在项目 C 中定义对于项目 A1 的依赖也是如此书写,但
dependencies的书写则是在项目 C 的build.gradle中。
buildscript { } 的使用
buildscript 这个代码段所提供的功能,是为 build.gradle 脚本本身提供配置,而不是为项目提供配置。在多项目构建中,可以在根项目的 build.gradle 中进行 buildscript 的声明,这样可以使其中的配置在全部子项目中都可用。
额外属性定义
在 build.gradle 中使用 def 关键字定义的内容为本地变量,其作用域是有限的。如果定义通贯全局的属性,需要在 ext { } 中定义。在这其中定义的属性一般称为额外属性,这些额外属性是定义在其存在的作用域下的,如配置文件本身或者任务本身。
一般用额外属性来定义依赖项的版本号,这通常可以达到修订一个位置即可影响全局的效果。
例如:
ext {
springBootVersion = '2.2.2.RELEASE'
}
额外属性既可以在 buildscript 中定义,也可在项目配置文件的顶级范围定义,两种定义位置的区别仅在于其能够影响的范围不同。
任务定义
简单任务定义
任务由 task 关键字定义,最简单的任务定义格式为:
task taskName {
doLast {
// 任务内容
}
}
任务依赖
一个任务可以对另一个任务建立依赖,具备依赖的任务,会在全部依赖任务都执行完成后才会执行。具有依赖项的任务定义格式为:
task taskA(dependsOn: taskB) {
doLast {
// 任务内容
}
}
更改任务行为
任务在定义后并不是可变的,之前我们定义任务都是使用 doLast 关键字,这个关键字表示之后定义的内容要放在最后执行,多个 doLast 定义则会让被定义内容依次执行。其他还有 doFirst 关键字可供使用,这会让被定义内容在任务靠前的位置执行。
使用 taskName.doLast { } 和 taskName.doFirst { } 的缩略语法可以实现任务的快速定义。
默认任务
默认任务通过 defaultTasks 关键字定义,其后的默认任务使用逗号分隔依次列出。默认任务执行时会按照列出顺序执行。
任务定位
任务可以通过 taskName 的方式访问,也可以通过 tasks.taskName 的方式访问,访问不同项目中的 task 可以通过 projectName.taskName 的方式访问。
如果使用 tasks 访问不同的项目下的任务,则需要使用 tasks.getByPath(":projectName:taskName") 的方式进行访问。
命令行任务
定义执行命令行的任务可以通过定义类型为 Exec 的核心任务完成。该类型的任务提供了一个 commandLine 方法,其接受若干个字符串参数。这些参数分别对应终端命令行中的参数,第一个参数为可执行文件或命令,第二个参数开始为命令的参数部分。
如果需要执行Webpack来对Web项目中的内容进行打包,可以使用此任务进行定义。例如:
task webpack(type: Exec) {
commandLine "$projectDir/node_modules/.bin/webpack", "app/index.js", "$buildDir/js/bundle.js"
}
文件处理
获取文件
单一文件的获取可以通过 file() 方法完成,该方法可以接受任意可以表达一个文件的参数,包括:相对路径、绝对路径、 java.io.File 对象、 java.nio.file.Path 对象等。
多个文件的获取则是通过 files() 方法完成,该方法可以接受任意多个参数,可接受的参数类型与 file() 方法相同。files() 方法返回的文件集可以使用 + 和 - 来进行文件集的增减操作,操作符两端的操作数要求都是文件集的类型。
获取一个文件树需要使用 fileTree() 方法,该方法一般使用一个 Map 进行初始化,常用的键值有以下五个:
dir,指定文件树的基础路径。include,指定要包含的文件路径模式,接受一个字符串。includes,指定要包含的文件路径模式集合,接受一个字符串列表。exclude,指定要排除的文件路径模式,接受一个字符串。excludes,指定要排除的文件路径模式,接受一个字符串列表。
fileTree 还提供了独立的 include() 和 exclude() 方法,其作用与初始化时使用的键值功能相同。包含和排除使用的文件路径模式都是采用 Ant-Style 模式。
与文件树功能类似的还有 zipTree 和 tarTree,分别提供 ZIP 和 TAR 压缩文件的树形访问功能。
复制文件
Gradle 内置了若干核心任务,定义这些任务时可以通过给定 type 参数来将自定义任务声明为核心任务,核心任务中会提供许多内置的强大语法。复制文件就是一个核心任务,可以通过 task copyTask(type: Copy) { } 来定义。
在复制文件任务中,可以通过 from 方法(可以不带括号),定义要复制的内容,该方法接受 files() 方法可接受的参数。into 方法可以定义要复制到的位置,该方法接受一个 file() 方法可接受的参数。复制任务中可以有多个 from 方法,但只应该有一个 into 方法。若需要像 files() 方法一样定义路径的包含与排除,可以直接使用 include 和 exclude 方法。
Sync 类型任务是 Copy 类型任务的扩展,可以用来在两个位置间进行文件的同步,会自动删除目标路径中未被复制的内容。
Zip 类型任务与 Copy 类型任务相似,但是其是用来创建一个压缩包。与 Zip 相似的任务还有: Tar、 Jar、 War 和 Ear。
压缩任务中可以通过以下属性来自定义压缩包的特性:
| 属性名 | 类型 | 默认值 | 用途 |
|---|---|---|---|
| archiveName | String | baseName-appendix-version-classifier.extension | 生成压缩包的文件名 |
| archivePath | File | destinationDir/archiveName | 生成压缩包的绝对路径 |
| destinationDir | File | JAR/WAR:project.buildDir.libraries;ZIP/TAR:project.buildDir/distributions | 生成压缩包的存储路径 |
| baseName | String | project.name | 生成压缩包的基础名称 |
| appendix | String | null | 生成压缩包的附加名称 |
| version | String | project.version | 生成压缩包的版本名称 |
| classifier | String | null | 生成压缩包的分类名称 |
| extension | String | zip、jar、war、tar、tgz、tbz2等 | 生成压缩包的文件名后缀 |
常用Plugin的使用要点简介
Java Plugin
Java插件引入了一个 sourceSets 的属性,用来定义源代码文件的位置,其中规定了 main 和 test 两类源代码的路径,每一类下面又分设 java 与 resources 两个属性,分别定义 Java 代码与资源文件的位置。
可以在配置文件的顶级位置使用以下示例代码来定义源代码位置:
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources']
}
}
test {
java {
srcDirs = ['src/test/java']
}
resources {
srcDirs = ['src/test/resources']
}
}
}
Java 插件提供了若干依赖管理方法,用来声明每个依赖的使用方法,这些依赖管理方法在所有继承 Java 插件的插件中都可以使用。
| 依赖管理方法 | 继承自方法 | 依赖特性 |
|---|---|---|
| compile | 编译时及运行时依赖 | |
| compileOnly | 仅编译时依赖,运行时不依赖 | |
| compileClasspath | compile,compileOnly | 只在编译Classpath时依赖 |
| runtime | compile | 仅运行时依赖 |
| testCompile | compile | 编译测试时的额外依赖 |
| testCompileOnly | 仅编译测试时的依赖,运行时不依赖 | |
| testCompileClasspath | testCompile,testCompileOnly | 只在编译Classpath测试时依赖 |
| testRuntime | runtime,testCompile | 仅测试运行时依赖 |
Java Library Plugin
Java Library 插件扩展了Java插件的特性,提供了建立 Java Library 时如何向使用者暴露所使用的依赖的依赖管理方法。
api 依赖管理方法用于向使用者暴露 Java Library 所使用的依赖,这个暴露出来的依赖可以被使用者所使用,从而使使用者不必再额外引用依赖,并且可以加速编译。implementation 以来管理方法会将依赖隐藏,使依赖仅供 Java Library 使用。
一般可以用以下标准来决定某一个依赖项是使用 api 还是 implementation :
- 依赖中的类符合以下条件的可以使用
api进行管理:- 在基类和接口定义中使用的类;
- 在公有方法参数中使用的类,包括在泛型中使用的类;
- 在公有字段中使用的类;
- 在公有注解中使用的类;
- 依赖中的类符合以下条件的可以使用
implementation进行管理:- 仅在方法体内使用的类;
- 仅在私有成员中使用的类;
- 仅在内部类中使用的类。
Application Plugin
Application 插件用来创建可执行的 JVM 应用。Application 插件隐式继承了 Java 插件,并具备 Java 插件的全部性能。
可以通过 mainClassName 属性来定义应用的主类(main class),即启动类。还可以通过 applicationDefaultJvmArgs 来定义应用启动的默认JVM设置。
WAR Plugin
WAR 插件主要是增加了打包 .war 文件的能力,同样继承了 Java 插件,并在其 sourceSets 中增加了 src/main/webapp 的路径作为需要打包 Web Application 资源的位置。
插件可以通过 war { } 来配置所形成的 .war 文件中的内容。具体见以下示例:
war {
from '' // 将编译后的源码添加到发布包顶层
webInf { from '' } // 指定要加入WEB-INF目录下的文件
classpath '' // 指定要加入WEB-INF/libs目录下的库
webXml = file('') // 指定WEB-INF/web.xml的来源
}
Kotlin Plugin
Kotlin 插件同样继承了 Java 插件,并在 sourceSets 中增加了 src/main/kotlin 和 src/test/kotlin 的源代码目录。
Kotlin 插件还提供了一些用于配置 Kotlin 编译的属性,同样需要在配置文件的顶级范围(plugins 之后)内的以下配置块内设置:
compileKotlin {
kotlinOptions {
}
}
常用的配置项有:
| 配置项名称 | 功能 | 可选值 | 默认值 |
|---|---|---|---|
| allWarningsAsErrors | 将警告视同错误进行报告 | false | |
| suppressWarnings | 忽略全部警告 | false | |
| apiVersion | 指定仅可以使用的库版本 | 1.0,1.1,1.2,1.3 | |
| languageVersion | 指定源代码使用的语言版本 | 1.0,1.1,1.2,1.3 | |
| jvmTarget | 生成的 JVM 字节码的版本 | 1.6,1.8,9,11,12 | 1.6 |
| noJdk | 不在 classpath 中包含Java运行时 | false | |
| noReflect | 不在 classpath 中包含 Kotlin 反射实现 | true | |
| noStdlib | 不在 classpath 中包含 Kotlin 运行时 | true |
Maven Publish
Maven Publish 插件主要提供了将打包后的 Jar 库发布到 Maven 远程私服仓库的功能。在使用 plugins { id 'maven-publish' } 引用之后,就可以在 build.gradle 中在 publishing { } 中进行发布配置。Maven Publish 的配置需要配置要上传的内容以及远程私服仓库的位置。
以下给出一个简单的示例配置。
plugins {
id 'java-library'
id 'maven-publish'
}
publishing {
// 发布内容配置
publications {
maven(MavenPublication) {
// GAV 坐标如果不填,则默认使用项目的 GAV 描述
groupId ''
artifactId ''
version ''
// 上传 Jar 包,如果是 War 包则填 components.web
from components.java
// 上传源码
artifact sourceJar {
classifier "sources"
}
// 定义上传内容的 POM
pom { }
}
}
// 目标仓库配置
repositories {
maven {
// 仓库地址
url ""
// 仓库登陆用户名和密码
credentials {
username ''
password ''
}
}
}
}
要将进行发布只需要执行任务 publish 即可,如果运行任务 publishToMavenLocal 则是发布到 Maven 本地仓库。
IDEA Plugin
主要用于提供生成 IntelliJ IDEA 项目所使用的文件,使项目可以使用 IDEA 的 Open Project 功能打开。常用的 Task 主要有以下四个:
ideaProject,生成.ipr文件,只会加入到根项目中;ideaModule,生成.iml文件,定义 Module;ideaWorkspace,生成.iws文件,只会加入到根项目中;idea,依赖于以上三个 Task。
在高版本 Java 中的应用
自从 Java 9 引入模块系统之后,Java 应用就有了两种开发模式:传统模式和模块模式。在传统模式中,无论基于哪个 Java 版本开发,Gradle 配置脚本都是一致的,可以直接采用目前可以见到的所有构建配置的书写方法。
建立使用 JPMS 的应用
JPMS 是 Java 9 引入的模块系统,这是 Java 自诞生以来非常重要的改变之一。模块系统的引入降低了 Java 应用的大小,提升了应用的运行效率。
使用 JPMS 的应用需要定义 module-info.java 文件,并在其中引入其他所需的模块,并定义自身要导出的模块。Gradle 没有直接提供 JPMS 的支持,需要通过插件来完成这个功能。要引入插件,可以仿照以下配置书写。
buildscript {
repositories {
maven { url "http://plugins.gradle.org/m2/" }
}
dependencies {
classpath "org.javamodularity:moduleplugin:1.6.0"
}
}
之后就可以在项目配置中应用模块插件了。
plugins {
id 'java'
id 'org.javamodularity.moduleplugin'
}
对于模块的引用需要在应用的两个位置声明,一个是 Gradle 构建脚本中的 dependencies 部分,一个是应用的 module-info.java 中。
如果一个项目由多个模块组成,那么需要将所有的模块设置成一个主项目的各个子项目,其中主项目的 build.gradle 可以使用以下内容。
buildscript {
repositories {
maven { url "http://plugins.gradle.org/m2/" }
}
dependencies {
classpath "org.javamodularity:moduleplugin:1.6.0"
}
}
plugins {
id 'org.javamodularity.moduleplugin' version '1.6.0' apply false
}
group 'com.example'
version '1.0-SNAPSHOT'
subprojects {
apply plugin: 'java'
apply plugin: 'org.javamodularity.moduleplugin'
sourceCompatibility = 11
targetCompatibility = 11
repositories {
mavenCentral()
}
}
其中不携带主类的模块无需更多配置,只需要应用 java 插件即可。携带主类的主模块可以使用以下 build.gradle 配置。
plugins {
id 'application'
}
group 'com.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
application {
mainClassName = "$moduleName/com.example.main.Main"
}
dependencies {
implementation project(':module-func')
testCompile group: 'junit', name: 'junit', version: '4.12'
}
主项目的 setting.gradle 中需要使用类似以下配置。
rootProject.name = 'main-project'
include 'module-host'
include 'module-func'
建立使用 JPMS 的 Spring 应用
目前 Spring 应用都习惯性使用 Spring Boot 建立,要在 Spring Boot 应用中使用 JPMS ,必须使用 Spring Boot 2.0 以上的版本。在 Spring Boot 2.0 以上版本里,所有的 Jar 包都自动提供了用于 JPMS 的模块名称。可以直接在 module-info.java 中使用。
建立 JavaFx 应用
使用 Gradle 建立 JavaFx 13 的应用,首先需要构建普通 Java 11 应用。由于 JavaFx 13 需要最低 Java 11 来运行,所以 Gradle 构建目标一般为 Java 11,并且推荐使用 JPMS 来构建。
图形界面应用一般会打包为可执行版本,所以要使用的 Gradle 插件就更多一些。
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.8'
id 'org.beryx.jlink' version '2.17.0'
}
其中 JavaFx 插件用于配置 JavaFx 所需要的版本以及引入模块,并指定主函数所在类,所以基本上都是以以下格式为主。
javafx {
version = '13.0.1'
modules = ['javafx.controls', 'javafx.fxml']
}
mainClassName = "$moduleName/fxapp.MainApp"
其中 version 用于指定应用所使用的 JavaFx 版本,modules 用于指定应用所要引入的 JavaFx 模块。这里所声明的模块应该在应用的 module-info.java 文件中也同样引入。如果不使用 JPMS 构建应用,则可以省略 module-info.java,并且不需要使用后文的 jlink 插件。
module fxapp {
requires javafx.controls;
requires javafx.fxml;
// 这里需要使用opens将包含有FXML Controller类的包开放给javafx.fxml
// 如果有多个包,则需要逐个开放
opens fxapp to javafx.fxml;
exports fxapp;
}
如果只需要使用 ./gradlew run 执行应用,那么到这里就可以了。但是如果打算构建自定义的运行时并打包应用,可以使用 jlink 插件。jlink 插件的配置一般如下例所示。
jlink {
options = ['--compress', '2']
launcher {
name = 'fxapp'
}
}
其中 launcher 用来指定要启动的模块名称,也是最终编译输出的可执行文件名称。options 则是编译过程中的一些基本配置选项。
jlink插件需要在 Java 11 和 Gradle 4.8 及以上版本中运行,由 Java 提供的jlink命令提供支持。
