【问题标题】:Spring Boot multi module project with Gradle doesn't build使用 Gradle 的 Spring Boot 多模块项目无法构建
【发布时间】:2018-05-15 21:08:53
【问题描述】:

我正在开发一个包含多个模块的 Spring Boot 应用程序,我们正在使用 Gradle 来构建它。不幸的是,我无法正确配置 Gradle。

项目结构是这样的:

parent
  |
  + build.gradle
  |
  + settings.gradle
  |
  + core
  |   |
  |   + build.gradle
  | 
  + apis
  |   |
  |   + build.gradle
  |
  + services
  |   |
  |   + build.gradle
  | 
  + data
  |   |
  |   + build.gradle

当我尝试构建项目时,我收到类似error: cannot find symbol 的编译错误,说服务中使用的数据中的类没有被导入。我认为所有模块之间都是如此。

我的父 build.gradle 看起来像这样:

buildscript {
    ext {
        springBootVersion = '2.0.0.BUILD-SNAPSHOT'
    }
    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/snapshot" }
        maven { url "https://repo.spring.io/milestone" }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'eclipse'
apply plugin: 'idea'

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

    group = 'com.example'
    version = '0.0.1-SNAPSHOT'
    sourceCompatibility = 1.8
    targetCompatibility = 1.8

    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/snapshot" }
        maven { url "https://repo.spring.io/milestone" }
    }

    dependencies {
        testCompile('org.springframework.boot:spring-boot-starter-test')
    }
}

dependencies {
    compile project(':data')
    compile project(':services')
    compile project(':apis')
    compile project(':core')
}

jar {
    baseName = 'my-jar'
    version = '0.0.1-SNAPSHOT'
}

settings.gradle:

rootProject.name = 'my-app'
include ':apis'
include ':core'
include ':data'
include ':services'

其中一个孩子(核心)在它的 build.gradle 中有这个:

dependencies {
    compile('org.springframework.boot:spring-boot-starter-actuator')
    compile('org.springframework.boot:spring-boot-starter-quartz')
    compile('org.springframework.boot:spring-boot-starter-tomcat')
    runtime('com.h2database:h2')

    compile project(':data')
    compile project(':services')
    compile project(':apis')
}

services build.gradle 看起来像这样:

dependencies {
    compile('org.springframework.boot:spring-boot-starter-quartz')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    runtime('com.h2database:h2')

    compile project(':data')
}

其他的也只声明依赖项。

依赖结构如下所示:

core - apis, services, data

apis - services, data

services - data

data -

编译错误示例:

/my-app/services/src/main/java/com/example/my-app/business/IssuedTokenService.java:3: error: package com.examples.data.dao does not exist import com.examples.data.dao.IssuedToken;

/my-app/services/src/main/java/com/example/my-app/business/IssuedTokenService.java:4: error: package com.examples.data.repository does not exist import com.examples.data.repository.IssuedTokenRepository;

/my-app/services/src/main/java/com/example/my-app/business/IssuedTokenService.java:12: error: cannot find symbol 
    private IssuedTokenRepository issuedTokenRepository;

    symbol:   class IssuedTokenRepository
   location: class IssuedTokenService

/my-app/services/src/main/java/com/example/my-app/business/IssuedTokenService.java:15: error: cannot find symbol
   public void saveToken(IssuedToken issuedToken) {
                                  ^
   symbol:   class IssuedToken
   location: class IssuedTokenService

【问题讨论】:

  • 所以核心依赖于数据、服务和api,对吧?您是否也有其中之一取决于核心?你的实际错误是什么,你的依赖树是什么?通常你会有类似 services->data->apis->core 作为依赖链。
  • 根据您的描述,服务找不到数据类。所以重要的是你没有发布的服务模块的配置。贴出相关代码,以及准确完整的信息。
  • @JBNizet 我已经添加了错误消息和依赖项。就编译错误而言,这很简单。服务模块代码中使用的数据模块中的每个符号对于编译器来说都是未知的。
  • 我猜这是因为您将引导插件应用于所有项目。它们不是启动项目。它们只是普通的 Java 项目。只有顶层(我猜是奇怪的核心,它依赖于其他所有东西,因此是外壳而不是核心)应该是一个引导项目。
  • @JBNizet 我已经尝试过这样做,但是当引导插件不存在时,Gradle 无法识别任何 org.springframework.boot:spring-boot-starter- 依赖项。

标签: java spring spring-boot gradle build.gradle


【解决方案1】:

在您的实用程序(数据)项目中放置:

bootJar {
    enabled = false
}

jar {
    enabled = true
}

如果 kotlin dsl

tasks.getByName<BootJar>("bootJar") {
    enabled = false
}

tasks.getByName<Jar>("jar") {
    enabled = true
}

【讨论】:

  • 我的朋友非常感谢!我已经尝试解决我的依赖问题 2 天
  • 你能解释一下为什么我们需要添加这些行吗?
  • @Max 因为 spring boot 使用 JarLauncher 构建 jar,其结构与普通 jar 不同,它意味着可执行,并且您的类成为 spring-boot-jar 中的依赖项。上面的代码更改了构建结构并禁用了 bootJar 和 JarLauncher,将模块编译为没有 BOOT-INF 目录的标准 jar。这是一个普通的不可执行库。
  • 我把上面的代码放在subprojects { ... }。根据@agilob 的解释,根项目上的引导内容应该足够了。
  • 非常感谢!此答案应标记为正确。
【解决方案2】:
bootJar {
    enabled = false
}

jar {
    enabled = true
}

这对我有用。在我的情况下,使用带有多项目的 spring 云的 spring boot 并且 gradle 无法构建。有了这个解决方案!

【讨论】:

  • 尽管回复晚了,但我现在遇到了这个问题,你帮助了我..所以我不得不尊重这一点:D
【解决方案3】:

答案类似于this one

Gradle documentation 在多项目构建状态下:

“lib”依赖是一种特殊形式的执行依赖。它 导致首先构建另一个项目并添加 jar 其他项目的类到类路径。

因此,重新打包的 jar 会带来问题。

例如,如果项目B 依赖于项目A,并且项目A 应用了org.springframework.boot 插件,那么简单的compile project(':A') 依赖将不起作用,因为项目jar 在期间重新打包bootRepackagebootJar 任务。生成的 fat jar 具有不同的结构,阻止 Gradle 加载其类。

在这种情况下,依赖项应该这样写:

dependencies {
  compile project(':A').sourceSets.main.output
}

直接使用源集的输出相当于在重新打包之前使用项目A的“正常”结果jar。

【讨论】:

【解决方案4】:

您应该从所有子模块(根 build.gradle 文件,allProjects 块)中排除 org.springframework.boot,它们是您的核心模块的依赖项,它将被构建到 fat-jar。

dependencyManagement 配置包含到所有spring-boot 管理的子模块中:

dependencyManagement {
    imports {
        mavenBom "org.springframework.boot:spring-boot-starter-parent:${springBootVersion}"
    }
}

问题的原因是核心模块 fat-jar 中没有子模块编译的 jar 文件。

【讨论】:

    猜你喜欢
    • 2020-04-13
    • 2021-08-03
    • 1970-01-01
    • 2018-10-06
    • 2015-02-14
    • 2016-06-11
    • 1970-01-01
    • 2020-06-26
    • 2018-10-07
    相关资源
    最近更新 更多