【背景】spring-boot項目,打包成可執行jar,項目內有兩個帶有main方法的類而且都使用了@SpringBootApplication註解(或者另外一種情形:你有兩個main方法而且所在類都沒有使用@SpringBootApplication註解),pom.xml以下html
<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>
【問題】java
[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]web
[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 classspring
【解決】apache
Note:參考官網描述,沒有指定<mainClass>或者繼承了spring-boot-starter-parent而且<start-class>屬性未配置時,會自動尋找簽名是public static void main(String[] args)
的方法... 因此插件懵逼了,兩個妹子和誰在一塊兒呢...
api
<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這個目標。app
- 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 pluginwebapp
[譯] 該插件重寫了清單文件(MANIFEST.MF,也就是jar裏面的清單文件),此文件管理着主類(Main-Class)和開始類(Start-Class)入口。清單文件中的Main-Class由layout控制maven
這裏的Start-Class就是咱們配置的<mainClass>,而Main-Class受layout屬性的控制,別被名字搞亂了(是否是很詭異?看看解決方法二就明白爲啥如此詭異了).... 來張圖直觀的感覺下,對應使用上面xml配置打包後的清單文件(MANIFEST.MF):
ide
layout屬性默認不須要配置,插件會自動推斷。不一樣的layout屬性清單文件裏面的Main-Class也會相應的不一樣。好比layout不配置或者配置爲JAR對應的Main-Class是JarLauncher,layout配置爲WAR對應的Main-Class是WarLauncher。
<properties> <start-class>com.xx.webapps.api.main.WebappsApiBidMain</start-class>
</properties>
【隨便說說】
說說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目錄下能夠看到:
【參考】
2.https://docs.spring.io/spring-boot/docs/2.0.0.BUILD-SNAPSHOT/maven-plugin//repackage-mojo.html