Spring Boot 多项目 Gradle --> 主类名未配置,无法解析

Posted

技术标签:

【中文标题】Spring Boot 多项目 Gradle --> 主类名未配置,无法解析【英文标题】:SpringBoot with multi-project Gradle --> Main class name has not been configured and it could not be resolved 【发布时间】:2019-06-05 16:21:19 【问题描述】:

我的项目结构如下:

RootProject
├── lib
     └── src
          └── main
               └── java
                    └── ...
├── test-project
     └── src
          └── main
               └── java
                    └── ...

└── build.gradle

我尝试使用 Gradle best practices 进行多项目构建,因此我在单个 build.gradle 文件中描述了整个构建过程。

“RootProject”只是一个没有任何代码的根项目,其唯一目的是为其子项目提供一个 build.gradle:“lib”和“test-project”。

“test-project”是一个使用“lib”作为编译依赖的SpringBoot项目(微服务)。

我常见的 build.gradle 如下所示:

plugins
    id 'java'
    id 'org.springframework.boot' version '2.1.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.6.RELEASE'



allprojects 
    repositories 
        jcenter()
    



subprojects 

    apply plugin: 'io.spring.dependency-management'
    apply plugin: 'org.springframework.boot'

    group = 'com.xxx.yyy'
    version = '1.0'

    sourceCompatibility = 1.8
    targetCompatibility = 1.8



project(":lib")

    apply plugin: 'java-library'

    dependencies 

        implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
        implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa'
        testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test'
    

    bootJar  enabled = false 
    jar  enabled = true 


project(":test-project")

    apply plugin: 'java'

    dependencies 
        implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
        implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa'
        implementation project(":lib")
        implementation ('mysql:mysql-connector-java')
    

“lib”和“test-project”都已成功构建。但是,当我尝试在根项目上执行“bootJar”任务(应该触发所有子项目上的“构建”任务)时,我收到以下错误:

Main class name has not been configured and it could not be resolved

有什么想法吗?

【问题讨论】:

如果主类在你的lib项目中,而spring-boot插件在test-project中,你需要在插件中配置主类。只是为了确定:主类上有@SpringBootApplication注解? 【参考方案1】:

多项目构建最佳实践简介

当你说:

我尝试遵循 Gradle 最佳实践进行多项目构建,因此我在单个 build.gradle 文件中描述了整个构建过程。

我不认为这实际上是一个好的做法,这也不是你提到的the guide 真正推荐的做法。

在指南介绍中:

虽然每个子项目都可以在完全隔离的情况下配置自己 其他子项目,子项目共享共同点是很普遍的 特征。然后通常最好在它们之间共享配置 项目,因此相同的配置会影响多个子项目。

=> 实际上,子项目之间共享的共同特征应该在根项目构建的中心位置进行配置。

在指南的后面(在this section 中)有一个示例,其中在根项目脚本中定义了子项目特定配置,但示例描述中有一个注释:

所有的构建逻辑都在根项目的构建脚本中。(2)

(2):我们在这里这样做,因为它使布局更容易一些。 我们通常将项目特定的东西放入各个项目的构建脚本中。

关于您的问题

我假设您的 lib 项目是一个普通的“简单”java lib 项目(没有 Spring 或 SpringBoot 依赖项),test-project 是包含 SpringBoot 应用程序类的项目(特别是 @SpringBootApplication 主应用程序类)。 按照上述最佳实践,您应该拥有三个不同的项目构建脚本:

root project: 用于定义子项目中的通用配置共享(java插件配置、存储库、共享依赖等...) lib project :此 lib 项目的特定配置(java-library 插件,特定依赖项,...) 没有理由将spring-boot 插件应用到这个子项目,这实际上是你的错误“找不到主类”的原因 如果这个项目依赖于 Spring-core 模块,你可以简单地应用 io.spring.dependency-management 插件(在这种情况下,在根项目构建中应用这个依赖插件是有意义的,在两个子项目中使用相同的 Spring 版本) test-projectproject:Spring Boot应用相关配置(SpringBoot插件和依赖)

示例

根项目构建

ext
    slf4jVersion = "1.7.25"


subprojects 
    apply plugin: "java"
    // if both subprojects share some Spring related dependencies, apply the Spring `io.spring.dependency-management` here.

    group = 'com.xxx.yyy'
    version = '1.0'

    sourceCompatibility = 1.8
    targetCompatibility = 1.8

    repositories 
        jcenter()
    

'lib' 项目构建

plugins
    id 'java-library'


dependencies 
    implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion
    // lib dependencies

'test-project' 构建

plugins      
    id "org.springframework.boot"  version "2.1.1.RELEASE"

apply plugin: 'io.spring.dependency-management'

dependencies 
    implementation project(":lib")
    implementation('org.springframework.boot:spring-boot-starter-web')
    testImplementation('org.springframework.boot:spring-boot-starter-test')
    implementation ('mysql:mysql-connector-java')
    // ...

编辑根据您的评论:如果 lib 项目需要 Spring Data 相关的东西,请按如下方式应用 io.spring.dependency-management(查看更多详细信息 in Spring reference guide)

plugins
    id 'java-library'
    id "org.springframework.boot"  version "2.1.1.RELEASE" apply false

apply plugin: 'io.spring.dependency-management'

dependencyManagement 
    imports 
        mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
    


dependencies 
    implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 
    // lib dependencies

【讨论】:

"lib" 是一个具有处理 JPA 的“通用”(例如可重用)代码的库。因此,“lib”需要在 Spring 中具有依赖关系,但它并不是可执行的。第二个项目(“test-project”)引用(“lib”)作为编译依赖项,并打算执行(spring boot) 正如我在回答中所说,如果您在 lib 中需要一些与 Spring 相关的部门,您只需应用 io.spring.dependency-management 插件,而不是“spring-boot”插件。我更新了我的答案。 "dependencyManagement" 部分丢失,现在可以编译。谢谢 关注点分离的优秀答案。并将(仅)抽象的 SLF4J 抽象 jar 放在“较低的项目”中。谢谢。

以上是关于Spring Boot 多项目 Gradle --> 主类名未配置,无法解析的主要内容,如果未能解决你的问题,请参考以下文章

多模块 Gradle 项目 - 从 Spring-Boot 1.5 迁移到 2.1

Spring boot 和 Gradle 多模块项目,无法正确加载依赖项

Eclipse(STS) 导入本地 spring boot (gradle)多项目

Spring Boot gradle 多模块项目未解决的引用错误

Gradle 与 Spring Boot 应用程序的多项目依赖关系

Spring Boot 多项目 Gradle --> 主类名未配置,无法解析