我有一个由以下部分组成的 Java 项目:
- 一个Java库
- 生产代码
- 该库的集成测试
- 使用该库的演示 Java 应用程序
集成测试和演示应用程序共享一些代码,因为在演示应用程序中可以选择和运行示例,所有这些示例也由集成测试执行。因此代码有以下四个部分:
- 图书馆生产代码
- 库集成测试
- 演示应用程序
- 示例代码
对我来说很明显(如果我错了,请纠正我)库生产代码和库集成测试应该是单独的源集,但在同一个模块中(=相同的 Gradle 子项目)。
由于演示应用程序使用与库不同的 Gradle 插件(java
+ application
vs. java-library
),因此我将其设为单独的模块(= 单独的 Gradle 子项目)。
代码部分相互之间具有以下依赖关系:
- 演示应用程序调用示例代码和直接一些库生产代码
- 集成测试调用示例代码并直接调用一些库生产代码
- 示例调用库生产代码
为了避免循环依赖,我没有将示例作为单独的模块(Gradle 子项目),而是在库模块中设置了另一个源。
因此我的项目具有以下结构:
my-multi-module-project/
├── build.gradle
├── gradlew
├── gradlew.bat
├── settings.gradle
├── demo-application/
│ ├── build.gradle
│ └── src/
│ └── main/
│ └── java/
│ └── ...
├── build.gradle
└── my-library/
├── build.gradle
└── src/
├── main/
│ └── java/
│ └── ...
├── test/
│ └── java/
│ └── ...
└── example/
└── java/
└── ...
...与以下内容my-multi-module-project/settings.gradle
:
rootProject.name = 'my-multi-module-project'
include 'my-library'
include 'demo-application'
这个项目结构对这个项目有意义吗,还是我应该改变它?
我应该如何设置源集之间的依赖关系,这些依赖关系尚未由使用的插件的默认值处理?
我已经尝试exampleOutput
在库模块中使用自定义配置:
内容my-multi-module-project/build.gradle
:
plugins {
id 'base'
}
allprojects {
repositories {
jcenter()
}
}
内容my-multi-module-project/demo-application/build.gradle
:
plugins {
id 'java'
id 'application'
}
dependencies {
implementation project(path: ':my-library', configuration: 'exampleOutput')
implementation project(path: ':my-library')
}
run {
standardInput = System.in
}
mainClassName = 'com.example.mylibrary.demoapplication.MainClass'
内容my-multi-module-project/my-library/build.gradle
:
plugins {
id 'java-library'
}
sourceSets {
example {
java
resources
compileClasspath += sourceSets.main.output
runtimeClasspath += sourceSets.main.output
}
test {
compileClasspath += sourceSets.example.output
runtimeClasspath += sourceSets.example.output
}
}
configurations {
exampleOutput
}
dependencies {
exampleOutput sourceSets.example.output
// Use JUnit test framework
testImplementation("org.junit.jupiter:junit-jupiter-api:5.4.2")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.4.2")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.4.2")
}
test {
useJUnitPlatform()
}
这适用于./gradlew run
and ./gradlew test
。
但现在我需要一个生产安装,不能使用 Gradle。所以我跑
./gradlew installDist
然后尝试运行
./demo-application/build/install/demo-application/bin/demo-application
我从代码部分得到了一个java.lang.NoClassDefFoundError
关于类的信息,实际上,在 中,有一个用于库生产代码 ( ) 的 JAR 文件和一个用于演示应用程序 ( ) 的 JAR 文件,但没有一个用于示例。相反,有一个与源集的 Java 包结构相对应的文件夹结构,其中包含示例 Java 类的文件。example
demo-application/build/install/demo-application/lib
my-library.jar
demo-application.jar
example
*.class
因此,由./gradlew distZip
和生成的档案./gradlew distTar
同样无法使用。
如何配置我的项目,以便分发产品的安装/生产也能正常工作?