You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gradle子项目间依赖声明方法咨询(附示例代码)

嘿,我来帮你搞定Gradle多项目里依赖声明的正确姿势,先看看你现有配置里的几个小问题,再给你一套标准的实现方案~

先聊聊你现有配置的可优化点
  • sourceSets配置:你把srcDirs设为['./']会把项目根目录下所有文件都当作源码,这不符合Gradle的默认规范,除非你有特殊的目录结构需求,不然建议用默认的src/main/java结构,能减少很多不必要的配置。
  • 依赖配置过时:你用了compile project(':p2'),但Gradle从5.x版本开始就废弃了compile这个配置,现在推荐用implementation(如果不需要把依赖暴露给上层项目)或者api(如果依赖需要被上层项目感知)。
  • Jar的Class-Path配置问题:你当前的configurations.runtime.files.collect { it.name }.join('')有两个问题:一是runtime配置已经被废弃,应该用runtimeClasspath;二是直接拼接文件名的话,当子项目的Jar不在同一目录时会找不到依赖,而且多项目构建里通常不需要手动设置Class-Path,Gradle会自动处理依赖传递,或者用更便捷的插件来打包可执行Jar。
正确的多项目依赖配置方案

首先得明确你的项目结构,多项目构建必须在根目录的settings.gradle里声明子项目,假设你的结构是这样的:

根项目/
├── settings.gradle
├── p1/ (Java应用项目)
│   └── build.gradle
└── p2/ (Java库项目)
    └── build.gradle

1. 根目录的settings.gradle

先注册两个子项目:

include ':p1', ':p2'

2. Java库项目(p2)的build.gradle

你用java-library插件是完全正确的,这个插件专门为库项目设计,提供了api和implementation来控制依赖的可见性:

plugins {
    id 'java-library'
}

// 除非你必须用自定义源码目录,否则注释掉这段,用默认的src/main/java结构
// sourceSets {
//     main {
//         java {
//             srcDirs = ['./']
//         }
//     }
// }

// 库项目一般不需要配置Jar的Class-Path和Main-Class,除非有特殊需求
// jar {
//     manifest.attributes(
//         // 这里不需要设置Main-Class,库项目没有主入口
//     )
// }

// 如果你的库有外部依赖,比如Guava,按需选择api或implementation
// dependencies {
//     api 'com.google.guava:guava:32.1.3-jre' // api会把依赖暴露给依赖此库的项目
//     // implementation 'xxx' // implementation的依赖仅在库内部可见
// }

3. Java应用项目(p1)的build.gradle

推荐用application插件,它比单纯的java插件更适合应用项目,能自动处理主类配置、依赖打包和运行任务:

plugins {
    id 'java'
    id 'application' // 强烈推荐,简化可执行Jar的配置
}

// 同样,优先用默认源码目录,特殊情况才自定义
// sourceSets {
//     main {
//         java {
//             srcDirs = ['./']
//         }
//     }
// }

// 声明对p2的依赖,用implementation就足够了(应用项目不需要把p2的依赖暴露给其他项目)
dependencies {
    implementation project(':p2')
}

// 用application插件直接指定主类,自动处理Class-Path
application {
    mainClass = 'Main' // 替换成你的主类全限定名
}

// 如果你一定要手动配置Jar(不推荐,用application插件的distZip/distTar更方便),可以这么修改:
// jar {
//     manifest {
//         attributes(
//             'Main-Class': 'Main',
//             // 用runtimeClasspath替代过时的runtime,并且要注意路径匹配
//             'Class-Path': configurations.runtimeClasspath.files.collect { "../${it.name}" }.join(' ')
//             // 路径需要根据最终Jar的存放位置调整,这里假设p2的Jar在同一父目录下
//         )
//     }
// }

// 要是想打包成单个包含所有依赖的可执行Jar,可以用Shadow插件
// plugins {
//     id 'com.github.johnrengelman.shadow' version '8.1.1'
// }
// shadowJar {
//     mainClass = 'Main'
// }
一些最佳实践
  • 尽量遵循Gradle的默认项目结构,减少自定义配置的复杂度,默认结构是src/main/java放源码,src/main/resources放资源文件。
  • 彻底抛弃过时的配置:compile、runtime、testCompile等,改用implementation、api、runtimeOnly、testImplementation等。
  • Java应用优先用application插件,它提供了run任务直接运行项目,还能生成包含依赖的分发包;如果需要单个可执行Jar,用Shadow插件是最便捷的方式。

内容的提问来源于stack exchange,提问作者Paulo Marcio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:27:31