[IntelliJ IDEA + EduTools] 从零开始编写一套 Java 教材(三)

tech2026-04-09  1

目录

[IntelliJ IDEA + EduTools] 从零开始编写一套 Java 教材(零)

[IntelliJ IDEA + EduTools] 从零开始编写一套 Java 教材(一)

[IntelliJ IDEA + EduTools] 从零开始编写一套 Java 教材(二)

上期回顾

第三课 Gradle 构建脚本

第0节 build.gradle

第1节 settings.gradle


上期回顾

上一节课,我们介绍了与 EduTools 有关的4种 YAML 文件的格式。在日常的开发过程中,很难遇到需要我们人为编辑这些 YAML 文件的情况,EduTools 中的 Course Creator 工具会辅助我们进行数字教材的编写工作。

这一节课,我们将着重讲解 Gradle 项目的2个核心配置文件:build.gradle 和 settings.gradle 。


第三课 Gradle 构建脚本

Gradle 是一个以 Groovy 语言为项目构建脚本语言的自动化构建工具,支持 Java / Groovy / Scala / Kotlin 等各类 JVM 编程语言。build.gradle 与 settings.gradle 是项目的核心,它们共同管理着 Gradle 项目的一切。IntelliJ IDEA 会首先启动 Gradle ,Gradle 执行 *.gradle 构建脚本并生成各项配置,IntelliJ IDEA 自动分析这些配置,并将其与自身的设置进行同步,这正是我们在 IntelliJ IDEA 中打开 Maven / Gradle / SBT 项目时会先『加载项目结构』再『导入 IntelliJ IDEA 项目』的原因。

我们的教程项目结构本质上是一个 Gradle 多子项目结构。单一项目的 Gradle 构建脚本可能十分简单,但对于拥有四层目录分级的大型数字教程项目而言,一个正确的配置脚本至关重要。EduTools 已经为我们生成了这样的构建脚本,我们要做的只是读懂它、理解它。

 

第0节 build.gradle

// 用于构建脚本自身的配置 buildscript { // 远程仓库列表 repositories { // 华为云 Maven 远程仓库 maven { url "https://mirrors.huaweicloud.com/repository/maven/" } // 阿里云 Maven 远程仓库 maven { url "https://maven.aliyun.com/repository/public" } // Maven 中央仓库 mavenCentral() } } /** * 格式化 Gradle 标准输出 * * @param output 字节数组输出缓冲流 */ def printOutput(def output) { // 创建一个新的 Gradle 任务 return tasks.create("printOutput") { // 遍历缓冲流中的每一行内容 for (line in output.toString().readLines()) { // 补充前缀 println "#educational_plugin" + line } } } // 子项目统一配置 subprojects { // 引入 Java 语言插件 apply plugin: 'java' // 引入构建插件 apply plugin: 'application' // 限制 Java 语法为 JDK8 及以下 // JDK9 及更高版本的语法特性将不可使用 sourceCompatibility = 1.8 // 指定子项目所使用的远程仓库地址 repositories { maven { url "https://mirrors.huaweicloud.com/repository/maven/" } maven { url "https://maven.aliyun.com/repository/public" } mavenCentral() } // 子项目依赖项列表 dependencies { // 编译时使用的依赖项 compile group: 'org.apache.commons', name: 'commons-math', version: '2.2' // 测试编译时使用的依赖项 testCompile group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.6.2' } // 项目源文件列表 sourceSets { // 主源文件目录 main { java.srcDir 'src' } // 测试源文件目录 test { java.srcDir 'test' } } // 指定项目的主类名 mainClassName = project.hasProperty("mainClass") ? // 当项目配置了 mainClass 属性时 project.getProperty("mainClass") : "" // 获取配置值,否则留空 // 定义 Gradle 运行时的标准输出 def runOutput = new ByteArrayOutputStream() tasks.run.setStandardOutput(runOutput) // 指定构建过程最后执行的动作 tasks.run.doLast { printOutput(runOutput) } } // 通用项目,这个子项目用于编写其他子项目所共用的类或方法 project(':util') { // 特定项目的依赖项 dependencies { testCompile group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.6.2' } } // 配置除 util 之外的其他子项目 configure(subprojects.findAll { it.name != 'util' }) { // 添加 util 项目编译生成的类文件 dependencies { compile project(':util').sourceSets.main.output testCompile project(':util').sourceSets.test.output } }

 

第1节 settings.gradle

/** * 名称标准化(用于去除目录中的非法字符,转换为 Gradle 可接受的项目名) * * @param 任意字符串 * @return 格式化后的字符串 */ static String sanitizeName(String name) { // 将空格与各类标点符号统一替换为下划线 return name.replaceAll("[ /\\\\:<>\"?*|()]", "_") // 去除名称开头和结尾多余的小数点 .replaceAll("(^[.]+)|([.]+\$)", "") } // 指定根项目名 rootProject.name = 'Tutorial' // 递归遍历根项目目录的各级子目录 rootProject.projectDir.eachDirRecurse { // 如果项目不是任务目录,或者目录存在 .idea/ 子目录 if (!isTaskDir(it) || it.path.contains(".idea")) { // 忽略此目录 return } // 获取当前目录相对根项目目录的路径 def taskRelativePath = rootDir.toPath().relativize(it.toPath()) def parts = [] // 将相对路径中每一部分的目录名添加到数组中 for (name in taskRelativePath) { parts.add(sanitizeName(name.toString())) } // 将相对路径用连字符串起来,作为项目名 def moduleName = parts.join("-") // 引入项目名 include "$moduleName" // 指定子项目的项目根目录 project(":$moduleName").projectDir = it } /** * 检查一个目录是不是任务目录 * * @param 目录对象 * @return 拥有 src/ 目录的项目是任务项目,否则不是 */ static def isTaskDir(File dir) { return new File(dir, "src").exists() } // 引入全局工具项目 include 'util'

 

最新回复(0)