使用 srcDirs = ['mysrc'] 会完全替换默认 src/main/java,导致原代码不参与编译;正确做法是用 += 追加路径,如 srcDirs += 'mysrc',或显式重置时同步配置 resources、test 等路径。

sourceSets.main.java.srcDirs 覆盖默认路径会丢掉 src/main/java
直接写 srcDirs = ['mysrc'] 看似简洁,但这是最常踩的坑:它会**完全替换** Gradle 默认的 src/main/java,导致原目录下的代码不再参与编译。IDE 可能仍显示正常,但 gradle compileJava 会静默跳过那些文件。
正确做法是用 += 追加路径,保留原有约定:
sourceSets {
main {
java {
srcDirs += 'mysrc'
}
}
}这样 mysrc 和默认的 src/main/java 都会被扫描。
想彻底换掉默认结构?必须显式重置整个 srcDirs 数组
如果项目历史遗留严重(比如所有源码都在 src 根下),你确实需要弃用默认结构。这时必须用赋值语法,且要手动补全所有子路径,否则资源、测试等都会失效:
立即学习“Java免费学习笔记(深入)”;
-
srcDirs = ['src']只影响 Java 源码,resources仍走默认src/main/resources - 要一并迁移资源目录,得同步配置:
resources.srcDirs = ['src/resources'] - 测试代码同理:
test.java.srcDirs = ['test']
完整示例:
将后端 Java 接口文档转换为前端 TypeScript 类型定义(interface / type)。输入:飞书文档、Spring Boot 接口文档、Swagger/OpenAPI、手写 API 文档等。输出:包含请求参数与响应结果的 .md 文件,含完整 JSDoc 注释。触发关键词:Java 转 TS、接口转换、生成前端类型、接口文档转 TypeScript、DTO/VO/BO 转 interface、后端文档转前端类型、生成接口类型、类型定义生成。
sourceSets {
main {
java { srcDirs = ['src'] }
resources { srcDirs = ['src/resources'] }
}
test {
java { srcDirs = ['test'] }
resources { srcDirs = ['test/resources'] }
}
}Android 项目里改 sourceSet 要进 android {} 块
Android 插件不认顶层的 sourceSets 配置。比如你想把 Java 源码从 src/main/java 改到 android/src,必须写在 android 块内:
android {
sourceSets {
main {
java.srcDirs = ['android/src']
manifest.srcFile 'android/AndroidManifest.xml'
res.srcDirs = ['android/res']
}
}
}注意:setRoot() 会整体移动整个 sourceSet(含子目录),慎用;而 srcDirs = [...] 只控制源码位置,更可控。
生成的代码目录(如 generated)要追加,不能覆盖
很多工具(Lombok、MapStruct、Protobuf)会在构建过程中生成 Java 文件,放在 build/generated/source/... 或 src/main/generated。这类目录必须用 += 添加,否则原始源码就丢了:
sourceSets {
main {
java {
srcDirs += 'src/main/generated'
// ❌ 错误:srcDirs = ['src/main/generated'] → 原 src/main/java 失效
}
}
}另外,确保生成目录在 compileJava 任务执行前已存在,否则 Gradle 会跳过——常见于未配置 generateXxx 任务为 compileJava 的依赖。
真正麻烦的不是改路径本身,而是改完后没验证 gradle dependencies 和 gradle compileJava --info 的实际扫描路径。很多人只看 IDE 是否识别,结果 CI 编译失败才暴露问题。

















