线程异常 "main" java.lang.ClassNotFoundException - Spring Boot,多模块 gradle 项目

Exception in thread "main" java.lang.ClassNotFoundException - Springboot, multimodule gradle project

我知道这是一个常见问题,我不好意思问这个问题,但我无法弄清楚为什么我无法加载我的多模块 Springboot 应用程序的主要 class。

完整堆栈跟踪:

Exception in thread "main" java.lang.ClassNotFoundException: space.forloop.addon.app.Main
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:398)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:46)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)

A 有一个根级别 gradle.build 文件

plugins {
    id 'org.springframework.boot' version '2.4.1'
    id 'io.spring.dependency-management' version '1.0.10.RELEASE'
    id 'java'
}

repositories {
    mavenCentral()
}

bootJar {
    mainClass = 'space.forloop.addon.app.Main'
}

def javaProjects = [
        'addon-sync-app',
        // Removed, not important
]

javaProjects.each {
    name ->

        project(":$name") {
            apply plugin: 'org.springframework.boot'
            apply plugin: 'io.spring.dependency-management'
            apply plugin: 'java'

            repositories {
             // Removed, not important
            }

            dependencies {
             // Removed, not important
            }
        }
}

在包模块 addon-sync-app 中,我有另一个 build.gradle 文件,其中只有:

apply plugin: 'org.springframework.boot'

dependencies {
   // Removed, not important
}

查看 Configuring the Main Class 的文档,我确定要添加:

bootJar {
    mainClass = 'space.forloop.addon.app.Main'
}

gradle.build 文件在这里是正确的,但似乎不是。还有什么我可能错过的吗?

根据 gradle 文档,您可以尝试添加 'application' 插件。

https://docs.gradle.org/current/userguide/application_plugin.html

plugins {
    id 'application'
}
application {
    mainClass = 'space.forloop.addon.app.Main'
}

您使用 Spring 引导插件的方式有误。这是一个如此常见的错误,我认为他们需要更好地记录它或者让它开箱即用。好吧。

在 Gradle 多项目中,您通常定义支持库,然后定义一个或多个 运行 可用或可部署的应用程序。

从您的描述中我无法判断的一件事是您是否打算由根项目构建最终应用程序,或者它是否应该是 addon-sync-app 项目。鉴于名称,我假设是后者,但它可以是其中之一(但通常不会同时出现)。

当你将 Spring Boot 插件应用到一个项目(不管它是根项目还是子项目),并且你依赖默认值时,它将采用该项目并把它变成一个“胖罐子”,这需要一个特殊的类加载器 运行。这使得它不适合作为普通库。因此,当您尝试以正常方式依赖它时,您的 类 将找不到。

要修复它,您应该只将 Spring 引导插件应用于构建最终应用程序 jar 的项目。如果是 addon-sync-app,则将其从根和所有非应用程序子项目中删除。

相反,如果您希望根项目生成最终应用程序,则需要为所有必需的子项目创建依赖项,并且像以前一样,也从它们中删除 Spring 引导插件.

如果不应用 Spring 启动插件,您将失去的一件事是对 BOM 的自动依赖性,它定义了依赖项的默认版本。如果你想继续使用它而不创建你的库的胖罐子,有几种不同的方法来处理它。我在 .

上写了一个(有点太长了)答案