Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 1635|回复: 0

[默认分类] Spring Boot Maven Plugin打包异常及三种解决方法:Unable to find main class

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2020-8-17 09:21:49 | 显示全部楼层 |阅读模式
    【背景】spring-boot项目,打包成可执行jar,项目内有两个带有main方法的类并且都使用了@SpringbootApplication注解(或者另一种情形:你有两个main方法并且所在类都没有使用@SpringBootApplication注解),pom.xml如下

    1. <plugin>
    2.     <groupId>org.springframework.boot</groupId>
    3.     <artifactId>spring-boot-maven-plugin</artifactId>
    4.     <version>1.5.3.RELEASE</version>
    5.     <executions>
    6.         <execution>
    7.             <goals>
    8.                 <goal>repackage</goal>
    9.             </goals>
    10.         </execution>
    11.     </executions>
    12. </plugin>
    复制代码


      
    【问题】

    执行mvn clean package,报错如下(说点不相关的,使用install同理。因为spring-boot:repackage目标(goal)(下文会说)被绑定在package构建阶段(phases),而package阶段在install阶段之前,指定构建阶段之前的阶段都会执行。详细参见:Introduction to the Build Lifecycle

      [ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.5.3.RELEASE:repackage (default) on project webapps-api-bid: Execution default of goal org.springframework.boot:spring-boot-maven-plugin:1.5.3.RELEASE:repackage failed: Unable to find a single main class from the following candidates [com.xx.api.main.ApiBidMain, com.xx.webapps.api.main.WebappsApiBidMain]

    执行mvn clean package spring-boot:repackage,报错如下,不如上面日志详细

      [ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.5.3.RELEASE:repackage (default) on project webapps-api-bid: Execution default of goal org.springframework.boot:spring-boot-maven-plugin:1.5.3.RELEASE:repackage failed: Unable to find main class
      
      
    【解决】
      Note:参考官网描述,没有指定<mainClass>或者继承了spring-boot-starter-parent并且<start-class>属性未配置时,会自动寻找签名是
    1. public static void main(String[] args)
    复制代码
    的方法... 所以插件懵逼了,两个妹子和谁在一起呢...

      

    [推荐] 通用解决方法<configuration>下配置mainClass,指定程序入口。


    1. <plugin>
    2.     <groupId>org.springframework.boot</groupId>
    3.     <artifactId>spring-boot-maven-plugin</artifactId>
    4.     <version>1.5.3.RELEASE</version>
    5.     <configuration>
    6.         <mainClass>com.xx.webapps.api.main.WebappsApiBidMain</mainClass>
    7.     </configuration>
    8.     <executions>
    9.         <execution>
    10.             <goals>
    11.                 <goal>repackage</goal>
    12.             </goals>
    13.         </execution>
    14.     </executions>
    15. </plugin>
    复制代码


      
      Spring Boot Maven Plugin提供了几个目标(goal),我们在<executions>标签里配置的<goal>repackage</goal>对应spring-boot:repackage这个目标。

      
      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>,而Main-Class受layout属性的控制,别被名字搞乱了(是不是很诡异?看看解决方法二就明白为啥如此诡异了).... 来张图直观的感受下,对应使用上面xml配置打包后的清单文件(MANIFEST.MF):

      
      
      
      layout属性默认不需要配置,插件会自动推断。不同的layout属性清单文件里面的Main-Class也会相应的不同。比如layout不配置或者配置为JAR对应的Main-Class是JarLauncher,layout配置为WAR对应的Main-Class是WarLauncher。
      

    [有限制条件] 解决方法二如果你的pom继承自spring-boot-starter-parent(注意此前提),也可以直接在<properties>配置<start-class>(其实这里的start-class直接对应清单文件里的Start-Class):


    1. <properties>
    2.     <start-class>com.xx.webapps.api.main.WebappsApiBidMain</start-class>
    3. </properties>
    复制代码


      

    解决方法三:打包的的时候注释掉其他的@SpringBootApplication... 或者你有两处main方法并且都没有使用@SpringBootApplication注解,注释掉一个main方法..... 这就是第三种解决方法233333

      
      
    【随便说说】
      说说spring-boot:repackage这个目标。Spring Boot Maven Plugin这个插件包含一系列目标(goal),我们在<executions>标签里配置的<goal>repackage</goal>对应spring-boot:repackage这个目标,看下官方介绍

      spring-boot:repackage repackages your jar/war to be executable.
      Repackages existing JAR and WAR arcHives so that they can be executed from the command line using java -jar. With layout=NONE can also be used simply to package a JAR with nested dependencies (and no main class, so not executable).

      
      简单点说,这货重新打包个可执行的jar/war,可以在命令行使用-jar执行。如果指定layout为NONE那就没有主类只是打个普通的jar(不可执行),一般不会这么做。
      一般情况,这个目标会打一个新的jar/war,并把maven默认打的jar/war添加.original后缀,在target目录下可以看到:
      
      
    【参考】
    1.https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#build-tool-plugins-maven-packaging
    2.https://docs.spring.io/spring-boot/docs/2.0.0.BUILD-SNAPSHOT/maven-plugin//repackage-mojo.html
    3.https://stackoverflow.com/questions/23217002/how-do-i-tell-spring-boot-which-main-class-to-use-for-the-executable-jar
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-3-29 10:13 , Processed in 0.387466 second(s), 47 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表