我本地写了一个rabbitmq fanout模式的demo。consumer启动类和producer启动类都放到了一个springboot程序里。本地调试通过。
突然有个疑问,springboot项目是怎么来发现主启动类的呢?
我们知道,默认使用maven打包时,是个普通的可供依赖的jar包,仅包含来自项目源的资源和已编译的Java类,并不能单独运行。
鉴于上面的疑问,我在pom里加上spring-boot-maven-plugins,让这个项目作为一个springboot程序。
<build> <plugins> <plugin> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-maven-pluginartifactId> 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]
这才知道,在这种情况下,需要通过maven-plugin的configuration/mainClass节点来指定主启动类。
<build> <plugins> <plugin> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-maven-pluginartifactId> <configuration> <mainClass>com.fanoutconsumer.FanoutConsumerApplicationmainClass> configuration> plugin> plugins> build>
当然,话说回来,在企业应用中,我们通常也不会在一个springboot程序里写两个或多个启动类(只会写一个),所以也就不用显式指定启动类了。
springboot可执行程序包默认也是.jar。那么,对于同一个springboot项目,打出来的普通可依赖jar与springboot 可执行jar有什么区别呢?
我们看两种情况下的jar包里的文件结构及文件目录
1/2)作为普通可依赖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/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
Original: https://www.cnblogs.com/buguge/p/16373686.html
Author: buguge
Title: springboot有两个主启动类时,maven打包(可执行包)会报错,需指定启动主类
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/616474/
转载文章受原作者版权保护。转载请注明原作者出处!