spring-boot-maven-plugin插件找不到含有main的主类

it2024-12-30  16

【背景】

spring-boot项目执行mvn clean package打包时遇到一个问题,报错如下:

[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.3.4.RELEASE:repackage (default) on project behavior-data: Execution default of goal org.springframework.boot:spring-boot-maven-plugin:2.3.4.RELEASE:repackage failed: Unable to find a single main class from the following candidates [com.xxx.client.BehaviorDataApplication, com.xxx.client.domain.ReportRankDataDomain]

BehaviorDataApplication和ReportRankDataDomain类都有自己的main方法,BehaviorDataApplication是主启动类。看提示明显和spring-boot-maven-plugin插件打包有关系。

【解决】

这里其实就是spring-boot-maven-plugin插件在repackage时,会去寻找签名为public static void main(String[] args)的方法,但项目中有多个,所以插件懵逼了,不知道该找哪个。

直接说解决方式

在插件配置里手动配置下mainClass,指定程序入口。

<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>1.5.3.RELEASE</version> <configuration> <mainClass>com.xx.webapps.api.main.WebappsApiBidMain</mainClass> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin>

或者直接把项目中非启动类里的main方法都去掉,其实一般的springboot项目非启动类中添加main方法是不规范的。

【原因】

spring-boot-maven-plugin插件repackage的作用是在maven打包后再次打包,打包为一个fat jar,也就是可以通过命令行java -jar执行的jar或者war包。

repackage: create a jar or war file that is auto-executable. It can replace the regular artifact or can be attached to the build lifecyle with a separate classifier.

run: run your Spring Boot application with several options to pass parameters to it.

start and stop: integrate your Spring Boot application to the integration-test phase so that the application starts before it.

The plugin rewrites your manifest, and in particular it manages the Main-Class and Start-Class entries, so if the defaults don’t work you have to configure those there (not in the jar plugin). The Main-Class in the manifest is actually controlled by the layout property of the boot plugin

[译] 该插件重写了清单文件(MANIFEST.MF,也就是jar里面的清单文件),此文件管理着Main-Class和Start-Class入口。清单文件中的Main-Class由layout控制

这里的Start-Class就是我们配置的<mainClass> </mainClass>,来张图直观的感受下,对应使用上面xml配置打包后的清单文件(MANIFEST.MF): layout属性对应着是jar包还是war包,比如layout不配置或者配置为JAR对应的Main-Class是JarLauncher,layout配置为WAR对应的Main-Class是WarLauncher(java -jar启动时先去这个启动类,然后再去处理项目的启动类)。

【扩展】

下面具体的谈谈spring-boot:repackage,它重新打的包有什么不同,或者它如何将一个普通的jar 重新打包为一个可执行的fat jar。

Repackage existing JAR and WAR archives so that they can be executed from the command line using {@literal java -jar}. With <code>layout=NONE</code> can also be used simply to package a JAR with nested dependencies (and no main class, so not executable).

spring-boot-maven-plugin将maven打好的普通jar或war,再次进行打包。把之前maven默认打的包名字末尾添加上.original,效果如下:

然后我们分别进包内部去看下,为什么包大小相差这么多,为什么能直接可执行。

先看下maven打的较小的这个包里面是什么 其实就和在Tomcat部署时webapp自动解压出的文件结构相同。

然后看插件重新打的包: 关于SpringBoot jar可执行原理有很多文章参考,这里不再赘述。

SpringBoot基于jar包启动核心原理

最新回复(0)