使用Gradle的Spring Boot多模块项目无法构建

baj*_*mi2 18 java spring gradle build.gradle spring-boot

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

项目结构如下:

parent
  |
  + build.gradle
  |
  + settings.gradle
  |
  + core
  |   |
  |   + build.gradle
  | 
  + apis
  |   |
  |   + build.gradle
  |
  + services
  |   |
  |   + build.gradle
  | 
  + data
  |   |
  |   + build.gradle
Run Code Online (Sandbox Code Playgroud)

当我尝试构建项目时,我遇到编译错误,比如说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'
}
Run Code Online (Sandbox Code Playgroud)

settings.gradle:

rootProject.name = 'my-app'
include ':apis'
include ':core'
include ':data'
include ':services'
Run Code Online (Sandbox Code Playgroud)

其中一个孩子(核心)有这个在它的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')
}
Run Code Online (Sandbox Code Playgroud)

服务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')
}
Run Code Online (Sandbox Code Playgroud)

其他的也只声明依赖.

依赖结构如下所示:

core - apis, services, data

apis - services, data

services - data

data -
Run Code Online (Sandbox Code Playgroud)

编译错误的示例:

/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
Run Code Online (Sandbox Code Playgroud)

小智 42

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

bootJar {
    enabled = false
}

jar {
    enabled = true
}
Run Code Online (Sandbox Code Playgroud)

  • 你能解释为什么我们需要添加这些线? (4认同)
  • 我的朋友非常感谢!我已经尝试解决我的依赖问题 2 天了 (3认同)
  • @Max,因为spring boot使用JarLauncher构建jar,JarLauncher具有与普通jar不同的结构,这意味着它是可执行的,并且您的类成为spring-boot-jar中的依赖项。上面的代码更改了构建结构,并禁用了bootJar和JarLauncher,将模块编译为不带BOOT-INF目录的标准jar。这是一个普通的非可执行库。 (2认同)

jih*_*hor 12

答案与类似.

关于多项目构建的Gradle 文档说明:

"lib"依赖项是执行依赖项的一种特殊形式.它首先构建另一个项目,并将jar与另一个项目的类添加到类路径中.

因此,重新包装的罐子造成了问题.

如果说,项目B取决于项目A,该项目A具有org.springframework.boot应用到它的插件,一个简单的compile project(':A')依赖不会起作用,因为该项目罐子的过程中重新包装bootRepackagebootJar任务.生成的胖罐具有不同的结构,阻止Gradle加载其类.

在这种情况下,依赖项应按以下方式编写:

dependencies {
  compile project(':A').sourceSets.main.output
}
Run Code Online (Sandbox Code Playgroud)

直接使用源集的输出等同于A在重新打包之前使用"正常"生成的项目jar .

  • gradle的版本之间以及gradle的spring插件版本之间似乎都有很多变化 (2认同)

小智 5

bootJar {
    enabled = false
}

jar {
    enabled = true
}
Run Code Online (Sandbox Code Playgroud)

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


小智 5

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

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

dependencyManagement {
    imports {
        mavenBom "org.springframework.boot:spring-boot-starter-parent:${springBootVersion}"
    }
}
Run Code Online (Sandbox Code Playgroud)

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