1

我有一个由以下部分组成的 Java 项目:

  • 一个Java库
    • 生产代码
    • 该库的集成测试
  • 使用该库的演示 Java 应用程序

集成测试和演示应用程序共享一些代码,因为在演示应用程序中可以选择和运行示例,所有这些示例也由集成测试执行。因此代码有以下四个部分:

  • 图书馆生产代码
  • 库集成测试
  • 演示应用程序
  • 示例代码

对我来说很明显(如果我错了,请纠正我)库生产代码和库集成测试应该是单独的源集,但在同一个模块中(=相同的 Gradle 子项目)。

由于演示应用程序使用与库不同的 Gradle 插件(java+ applicationvs. 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 runand ./gradlew test

但现在我需要一个生产安装,不能使用 Gradle。所以我跑

./gradlew installDist

然后尝试运行

./demo-application/build/install/demo-application/bin/demo-application

我从代码部分得到了一个java.lang.NoClassDefFoundError关于类的信息,实际上,在 中,有一个用于库生产代码 ( ) 的 JAR 文件和一个用于演示应用程序 ( ) 的 JAR 文件,但没有一个用于示例。相反,有一个与源集的 Java 包结构相对应的文件夹结构,其中包含示例 Java 类的文件。exampledemo-application/build/install/demo-application/libmy-library.jardemo-application.jarexample*.class

因此,由./gradlew distZip和生成的档案./gradlew distTar同样无法使用。

如何配置我的项目,以便分发产品的安装/生产也能正常工作?

4

0 回答 0