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

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

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

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

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

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

我们知道,默认使用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有两个主启动类时,maven打包(可执行包)会报错,需指定启动主类

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/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Spring Bean生命周期

    本文基于图灵课堂周瑜老师的讲解整理,包括spring bean加载的过程,主要是扫描BeanDefinition以及初始化非懒加载单例Bean两部分,源码取自SpringFrame…

    Java 2023年6月8日
    077
  • Redis进阶知识一览

    Redis的持久化机制 RDB: Redis DataBase 什么是RDB RDB∶每隔一段时间,把内存中的数据写入磁盘的临时文件,作为快照,恢复的时候把快照文件读进内存。如果宕…

    Java 2023年6月5日
    071
  • 1.17(设计模式)观察者模式

    观察者模式定义了对象间一对多的关系,当一个对象状态发生变化时,所有依赖于该对象的对象也将发生变化。 这就可以使用观察者模式,显示十进制数和二进制数依赖于具体的数字,当具体数字发生变…

    Java 2023年6月8日
    075
  • SpringCloud中利用OAuth2实现客户端单设备登录

    在OAuth2生成Token的地方,源码里面会判断Token是否已经存在,如果存在且未过期直接返回旧的Token,如果不存在或已过期,则重新生成一个新的Token 这里做一个改动:…

    Java 2023年6月5日
    089
  • FastAPI+pydantic+SQLAlchemy返回多个数据

    问题 比如在ORM中查询 all, 那么使用 pydantic.from_orm获取对应的数据呢? 解决思路 只需要, 将一个字段对应为 List, 元素为对应 SQLAlchem…

    Java 2023年6月7日
    061
  • MybatisPlus 快速入门

    MybatisPlus 1.简介 官网:https://baomidou.com/pages/24112f/#特性 特性 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如…

    Java 2023年6月9日
    081
  • Nginx反向代理之巨坑underscores_in_headers

    一、背景 因为项目需求,在做Windows的相关的事情;基本架构就是Nginx–> Nginx –> IIS,在Linux机器上通过Nginx做…

    Java 2023年5月30日
    087
  • 第三方API对接如何设计接口认证?

    一、前言 在与第三方系统做接口对接时,往往需要考虑接口的安全性问题,本文主要分享几个常见的系统之间做接口对接时的认证方案。 二、认证方案 例如订单下单后通过 延时任务 对接 物流系…

    Java 2023年6月6日
    075
  • Java基础常识

    1.eclipse Run as application 快捷键 2.关于半角和全角 1.eclipse Run as application 快捷键 记得刚学时两个手并用按住了A…

    Java 2023年5月29日
    066
  • Eureka服务下线太慢,电话被告警打爆了

    某年某月的某一天,就像一张破碎的脸。。。 错了,重来。 某天,忽然发现大量的告警,经过多番调查研究考察(此处省略3000字),发现是由于 Eureka 服务下线太慢,而仍然有大量的…

    Java 2023年6月13日
    067
  • 简单的决策树以及代码实现

    简单的决策树 1. 本篇文章介绍 ​ 这篇文章旨在介绍最简易的决策树以及其复现代码,让大家基本了解决策树的基本流程,而不是被各种其它的诸如数据处理,剪枝等操作给搞迷糊了。 ​ 我的…

    Java 2023年6月7日
    082
  • 部署相关

    部署相关 C1.jar包启动 &#x95EE;&#x9898;&#x73B0;&#x8C61;&#xFF1A; nacos注释使用中文,通过…

    Java 2023年6月16日
    071
  • 2022-9-2 cookie 和 session

    当客户端关闭后,服务器不关闭,两次获取session是否为同一个?默认情况下。不是。 如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cooki…

    Java 2023年6月13日
    055
  • 异常

    异常 Java的基本理念是 “结构不佳的代码不运行”。—《Java编程思想》 Java中使用 异常来提供一致的错误报告模型。 那何为异常呢?日常…

    Java 2023年6月5日
    080
  • 【Java全栈进阶】-接口

    学习类的时候,知道类与类之间可以通过继承产生关系,接口和类之间可以通过实现产生关系,那么接口与接口之间会有什么关系呢? 多个接口之间可以使用 extends进行继承。 interf…

    Java 2023年6月7日
    073
  • Java 内存模型

    《Java虚拟机规范》中曾试图定义一种”Java内存模型”(Java Memory Model,JMM)来 屏蔽各种硬件和操作系统的内存访问差异,以实现让J…

    Java 2023年5月29日
    078
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球