0
点赞
收藏
分享

微信扫一扫

springboot有两个主启动类时,maven打包(可执行包)会报错,需指定启动主类

西特张 2022-07-12 阅读 55

springboot有两个主启动类时,maven打包(可执行包)会报错,需指定启动主类_spring

 

我本地写了一个rabbitmq fanout模式的demo。consumer启动类和producer启动类都放到了一个springboot程序里。本地调试通过。

springboot有两个主启动类时,maven打包(可执行包)会报错,需指定启动主类_spring_02

 

 

突然有个疑问,springboot项目是怎么来发现主启动类的呢?

 

springboot有两个主启动类时,maven打包(可执行包)会报错,需指定启动主类_spring_03

 

我们知道,默认使用maven打包时,是个普通的可供依赖的jar包,仅包含来自项目源的资源和已编译的Java类,并不能单独运行。

鉴于上面的疑问,我在pom里加上spring-boot-maven-plugins,让这个项目作为一个springboot程序。

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

这时,执行mvn package或mvn install命令时,发现报错--无法从两个候选的main程序类来选定一个作为主启动类。具体错误信息如下:
Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.2.0.RELEASE:repackage (repackage) on project fanoutx: Execution repackage of goal org.springframework.boot:spring-boot-maven-plugin:2.2.0.RELEASE:repackage failed: Unable to find a single main class from the following candidates [com.fanoutconsumer.FanoutConsumerApplication, com.fanoutproducer.FanoutProducerApplication]

这才知道,在这种情况下,需要使用configuration节点来指定主启动类。 

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.fanoutconsumer.FanoutConsumerApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>

 

 

当然,话说回来,在企业应用中,我们通常也不会在一个springboot程序里写两个或多个启动类(只会写一个),所以也就不用显式指定启动类了。

 

springboot有两个主启动类时,maven打包(可执行包)会报错,需指定启动主类_spring_04

 

springboot可执行程序包默认也是.jar。那么,对于同一个springboot项目,打出来的普通可依赖jar与springboot可执行jar有什么区别呢?

我们看两种情况下的jar包里的文件结构及文件目录

1)作为普通可依赖jar包的 fanoutx-1.0-SNAPSHOT.jar

fanoutx-1.0-SNAPSHOT.jar
application.yml
+com(项目已编译类,.class文件)
+META-INF
MANIFEST.MF
+maven
+org.example
+fanoutx
pom.properties
pom.xml

 

其中,META-INF/MANIFEST.MF内容为:

Manifest-Version: 1.0
Implementation-Title: fanoutx
Implementation-Version: 1.0-SNAPSHOT
Build-Jdk-Spec: 1.8
Created-By: Maven Archiver 3.4.0

 

 

2)作为springboot可执行jar包 的 fanoutx-1.0-SNAPSHOT.jar 是一个“胖jar”(有时称为“fat jars”)

fanoutx-1.0-SNAPSHOT.jar
+BOOT-INF
+classes
application.yml
+com(项目已编译类,.class文件)
+lib (项目依赖的lib包)
+META-INF
MANIFEST.MF
+maven
+org.example
+fanoutx
pom.properties
pom.xml
+org
+springframework
+boot
+loader
+archive
+data
ExecutableArchiveLauncher.class
+jar
JarLauncher.class
LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
LaunchedURLClassLoader.class
Launcher.class
MainMethodRunner.class
PropertiesLauncher$1.class
PropertiesLauncher$ArchiveEntryFilter.class
PropertiesLauncher$PrefixMatchingArchiveFilter.class
PropertiesLauncher.class
+util
WarLauncher.class

 

其中,META-INF/MANIFEST.MF内容为:

Manifest-Version: 1.0
Implementation-Title: fanoutx
Implementation-Version: 1.0-SNAPSHOT
Start-Class: com.fanoutconsumer.FanoutConsumerApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.2.0.RELEASE
Created-By: Maven Archiver 3.4.0
Main-Class: org.springframework.boot.loader.JarLauncher

 

 

可见,主要是有个 BOOT-INF ,还有 org/springframework/boot/loader/ 。---------->不仅具有来自项目的已编译Java类,还包括代码需要运行的所有 jar 依赖项,而且还具有启动Spring Boot应用程序所需的所有运行时库。
另外还可以看到,两者的 META-INF/MANIFEST.MF 文件里的内容不同,可执行jar里定义了Jarlauncher 及 Start-Class。

 

BTW,两者里,pom.xml内容与原始的pom.xml相同。pom.properties定义了artifact

version=1.0-SNAPSHOT
groupId=org.example
artifactId=fanoutx

 

 

【the end】

ref1:Maven-build之spring-boot-maven-plugin

ref2:baidu:Jarlauncher的实现原理

ref3:baidu:Springboot 创建可执行 Jar

举报

相关推荐

Java执行jar包指定启动类

0 条评论