Spring Boot Maven Plugin打包異常解決方案
【背景】spring-boot專案,打包成可執行jar,專案內有兩個帶有main方法的類並且都使用了@SpringBootApplication註解(或者另一種情形:你有兩個main方法並且所在類都沒有使用@SpringBootApplication註解),pom.xml如下
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>1.5.3.RELEASE</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </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>屬性未配置時,會自動尋找簽名是public static void main(String[] args)的方法... 所以外掛懵逼了,兩個妹子和誰在一起呢...
[推薦] 通用解決方法:<configuration>下配置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>
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 theMain-ClassandStart-Classentries,so if the defaults don't work you have to configure those there (not in the jar plugin). TheMain-Classin the manifest is actually controlled by thelayoutproperty 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):
<properties> <start-class>com.xx.webapps.api.main.WebappsApiBidMain</start-class> </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. Withlayout=NONEcan 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/
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
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。