Springboot 多模块依赖构建常见问题

4,279 阅读3分钟

笔者的项目使用SpringBoot+gradle构建,多模块间有依赖关系。本文记录遇到的构建问题与对应的解决方案。

模型代码

本文使用的一个简单项目来说明问题,项目简介如下:

  • 项目包含demo0和demo1两个子模块
  • demo0 模块是一个Springboot项目,提供一个Car类型的bean
  • demo1 模块依赖 demo0 模块,也是一个Springboot项目
  • demo1 引入demo0 中Car类型的bean

代码地址:

相关文档

Springboot 提供的 gradle 插件官方文档

关键知识点

本文主要涉及到springboot的构建知识,需理解springboot为gradle构建量身定制的构建插件的功效,在gradle的构建中主要体现为 jar 和 bootjar的配置。

多项目结构依赖配置

  • 在demo1的dependencies中引入对demo0模块依赖
implementation(project(":demo0"))
  • 在demo1的配置代码中设置对demo0的包扫描, 使得demo0中的bean生效
@ComponentScan("blog.peaksong.demo0")
@Configuration
class Config 

额外的设置

如果是一般的项目,这样的设置已经足够,但是被依赖的demo0是一个Springboot的项目,由于SpringBoot自带的gradle插件,demo0中构建任务jar被取消,bootjar被默认启动,故而我们会遇到以下报错。

  • 启动报错 Unresolved reference: demo0
22:45:32: Executing task ':demo1:classes'...

Starting Gradle Daemon...
Gradle Daemon started in 2 s 754 ms
> Task :demo0:compileKotlin UP-TO-DATE
> Task :demo0:compileJava NO-SOURCE
> Task :demo0:processResources NO-SOURCE
> Task :demo0:classes UP-TO-DATE
> Task :demo0:inspectClassesForKotlinIC UP-TO-DATE
> Task :demo0:jar SKIPPED

> Task :demo1:compileKotlin FAILED
e: C:\Users\PeakSong\IdeaProjects\juejin\juejin0\demo1\src\main\kotlin\blog\peaksong\demo1\Controller.kt: (3, 22): Unresolved reference: demo0
e: C:\Users\PeakSong\IdeaProjects\juejin\juejin0\demo1\src\main\kotlin\blog\peaksong\demo1\Controller.kt: (12, 32): Unresolved reference: Car

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':demo1:compileKotlin'.
> Compilation error. See log for more details

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 26s
3 actionable tasks: 1 executed, 2 up-to-date
22:46:08: Task execution finished ':demo1:classes'.

demo1 Springboot构建,会将所有依赖的jar加到最终的jar中,所以我们可以使用java -jar 直接启动,但是从日志中,我们可以看出demo0的jar任务被跳过,这导致demo0最终没有以jar形式引入,故而报错。 使得项目正常启动,我们只需要启用demo0的jar任务即可。

在demo0的build.gradle.kts中,再次运行项目成功

tasks.jar {
    enabled = true
}
  • 构建失败
22:55:24: Executing task 'bootJar'...

> Task :demo0:compileKotlin UP-TO-DATE
> Task :demo0:compileJava NO-SOURCE
> Task :demo0:processResources NO-SOURCE
> Task :demo0:classes UP-TO-DATE
> Task :demo0:bootJarMainClassName
> Task :demo0:bootJar FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':demo0:bootJar'.
> Failed to calculate the value of task ':demo0:bootJar' property 'mainClass'.
   > Main class name has not been configured and it could not be resolved

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s
3 actionable tasks: 2 executed, 1 up-to-date
22:55:26: Task execution finished 'bootJar'.

根项目的bootJar运行失败,提示demo的bootJar任务启动时,没有找到一个启动的主类。这个时候有两种方式修复,一种是给demo0添加一个Demo0Application的类,被@SpringBootApplication修饰,这样根项目的BootJar可以正常通过;另一种方法是直接关闭demo0的bootjar。 在实际项目中,一般采用第二种方法。

tasks.bootJar {
    enabled = false
}

总结

SpringBoot多模块依赖问题的构建 重点在于掌握Springboot自带插件对构建任务的设置。