我有一个使用Spring引导的多模块maven应用程序:
- spring boot parent
- myproject parent (both parent and module pom)
- module1
- module2
- module-it (integration tests)
在我的module-it中,我添加了其他模块作为依赖项。
当我用maven构建我的项目时,我得到了"构建成功":
mvn clean install
到目前为止一切顺利。
然而我希望我的每个模块在构建结束时都是可执行的jar。使用上面的设置,manifest没有定义,jar是不可执行的。为了解决这个问题,我在module1和module2 pom文件中添加了以下内容:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
在这个设置下,我的jar文件是可执行的,但是我不能再编译了。我在模块中使用的类找不到了。
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile (default-testCompile) on project module-it: Compilation failure: Compilation failure:
[ERROR] /home/user/<path-to-project>/testing/module-it/src/test/java/com/mycompany/testing/greeting/GreetingControllerIT.java:[20,17] cannot find symbol
[ERROR] symbol: class GreetingController
[ERROR] location: class com.mycompany.testing.greeting.GreetingControllerIT
[ERROR] /home/user/<path-to-project>/testing/module-it/src/test/java/com/mycompany/testing/hello/HelloControllerIT.java:[20,17] cannot find symbol
[ERROR] symbol: class HelloController
[ERROR] location: class com.mycompany.testing.hello.HelloControllerIT
[ERROR] /home/user/<path-to-project>/testing/module-it/src/test/java/com/mycompany/testing/greeting/GreetingControllerIT.java:[16,27] cannot find symbol
[ERROR] symbol: class GreetingController
[ERROR] /home/user/<path-to-project>/testing/module-it/src/test/java/com/mycompany/testing/hello/HelloControllerIT.java:[16,27] cannot find symbol
[ERROR] symbol: class HelloController
你能帮我理解为什么spring-boot-maven-plugin会让我的构建失败,以及我该如何解决这个问题吗?
先谢谢你的帮助。
4条答案
按热度按时间7bsow1i61#
要解决此问题,我们可以添加一个分类器,如文档自定义重新打包分类器中所述
然后插件变为:
afdcj2ne2#
您也可以将 repackage 目标参数 attach 设置为false:
nx7onnlm3#
至少对于
spring-boot-starter-parent:2.6.0
pom,spring-boot-maven-plugin
的配置包含用于执行repackage
目标的<id>repackage</id>
所以我还必须添加
<id>repackage</id>
行。完整配置:
7kqas0il4#
对一个老问题的迟来的回答,但是我在过去的几个小时里一直在研究这个问题。即使以前的回答是有帮助的,他们也没有解释为什么这个问题会发生。
对于其他可能遇到这个问题的人,这里有一个详细的解释,为什么它不工作
∮在一个果壳里∮
通常Maven会把你的应用程序打包成一个普通的. jar文件,所有编译好的类都放在. jar文件中一个众所周知的位置,所以编译器导入. jar作为一个库并加载可用的. class是非常直接的。
但是
spring-boot-maven-plugin
实际上是在修改. jar结构,以便在启动. jar应用程序时利用spring-boot逻辑,简而言之,. class不能作为"库"从生成的. jar中导入,因为spring类已经占用了众所周知的位置。详细说明
让我们通过一个示例来探讨这个问题
项目结构
让我们设想一个包含多个maven模块的项目,如下所示
给定以下pom.xml文件:
为什么它不建
让我们尝试打包应用程序
当然,它会悲惨地失败,错误为
cannot find symbol
,但为什么会这样呢?让我们看看失败构建后的架构:
spring-boot-maven-plugin
对 * application * 模块输出执行了以下操作:application-1.0.0-SNAPSHOT.jar
重命名为application-1.0.0-SNAPSHOT.jar.original
application-1.0.0-SNAPSHOT.jar
让我们来探索一下
application-1.0.0-SNAPSHOT.jar
的结构:正如你所看到的,. jar根目录下的. class文件是spring引导加载程序的类,而不是我们自己的. class,它们被放到
BOOT-INF/classes/
文件夹中。这不是常规的,当. jar作为依赖项导入时,它不会在这里搜索要导入的类。因此,当maven尝试打包 * integration-tests * 模块时,会失败,因为
application-1.0.0-SNAPSHOT.jar
中存在的类实际上是一堆spring类,而不是您尝试从 * application * 模块导入的类。如果您要查看
application-1.0.0-SNAPSHOT.jar.origial
的结构,它将是这样的:溶液
摆脱
spring-boot-maven-plugin
不是一个可以接受的解决方案;当然,您的项目将是可构建的,但生成的. jar不会是一个 Spring 启动的独立运行. jar。相反,您可以指示
spring-boot-maven-plugin
不替换原始jar,并使用另一个名称构建 * spring boot jar *。为此,您需要在 * application * 模块中配置
spring-boot-maven-plugin
:现在,当你构建你的项目时,你会有这样的东西: