一個(gè)項(xiàng)目IntelliJ IDEA的spring boot項(xiàng)目含有多個(gè)module础爬,module存在依賴關(guān)系。比如項(xiàng)目root項(xiàng)目為parent吼鳞,有三個(gè)module:common看蚜,service以及api,其中service依賴common赔桌,api依賴service供炎。項(xiàng)目結(jié)構(gòu)如下圖:
└─parent
├─api
├─common
└─service
依次配置各個(gè)層級(jí)的pom.xml文件,其中在父級(jí)項(xiàng)目parent的pom.xml中疾党,加入maven構(gòu)建插件:spring-boot-maven-plugin
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
在parent的根目錄下音诫,利用以下命令進(jìn)行打包,遺憾的是總提示錯(cuò)誤:“package common does not exist”雪位。
mvn clean package
原先以為可能compile存在問(wèn)題竭钝,利用以下命令執(zhí)行后,并未發(fā)現(xiàn)編譯錯(cuò)誤雹洗。
mvn clean compile
是否存在引入包沖突的問(wèn)題呢香罐?利用maven的-X參數(shù)執(zhí)行以下命令,并仔細(xì)查看了輸出信息时肿,并未發(fā)現(xiàn)任何有關(guān)包沖突的錯(cuò)誤庇茫。
mvn clean package -X
是否各個(gè)pom.xml文件配置不正確?查閱了相關(guān)文檔螃成,核對(duì)了N遍旦签,確信parent及各個(gè)module的pom.xml是配置無(wú)誤的查坪。
所有問(wèn)題的原因究竟在哪里?那刻自己也是沒(méi)了頭緒宁炫,能想到的原因都已一一排查偿曙。一邊不斷重試(有點(diǎn)盲目),一邊在網(wǎng)上搜索是否有類似問(wèn)題的解決方案淋淀。令自己沮喪的是遥昧,找了很久并沒(méi)有發(fā)現(xiàn)有人碰到完全一樣的問(wèn)題。
后面的心情可想而知朵纷,有種無(wú)力感炭臭,充滿了挫折感,甚至開(kāi)始懷疑人生……
然而作為技術(shù)人袍辞,天生有種執(zhí)著鞋仍,不解決問(wèn)題誓不罷休。所以帶著的內(nèi)心的挫敗感繼續(xù)想辦法解決這個(gè)問(wèn)題搅吁。
在“山重水復(fù)疑無(wú)路”以及“踏破鐵鞋無(wú)覓處”時(shí)威创,幸運(yùn)之神關(guān)顧了我,讓自己找了一些線索:有人說(shuō)是maven默認(rèn)的打包方式引起的谎懦,有個(gè)選項(xiàng)需要進(jìn)行正確設(shè)置:classifier肚豺,這個(gè)選項(xiàng)主要有兩個(gè)用途:標(biāo)識(shí)引入包的版本(包括可以用于指定jdk的版本)以及同時(shí)輸出不同的構(gòu)件(artifactid)。
由于主要關(guān)注打包的問(wèn)題界拦,所以找到了官方的文檔:Spring Boot Maven Plugin吸申,其中有段文字:
By default, the repackage goal will replace the original artifact with the repackaged one. That's a sane behavior for modules that represent an app but if your module is used as a dependency of another module, you need to provide a classifier for the repackaged one.
If you are usingspring-boot-starter-parent
, therepackage
goal is executed automatically in an execution with idrepackage
. In that setup, only the configuration should be specified as shown in the following example:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
This configuration will generate two artifacts: the original one and the repackaged counter part produced by the repackage goal. Both will be installed/deployed transparently.
根據(jù)文檔所述,如果一個(gè)module被另一個(gè)module所依賴享甸,那么需要顯示設(shè)置一個(gè)classifier截碴。對(duì)于spring-boot項(xiàng)目,可以設(shè)置:<classifier>exec</classifier>蛉威,在打包時(shí)會(huì)生產(chǎn)兩個(gè)構(gòu)件日丹,這兩個(gè)構(gòu)件都可以安裝或部署。根據(jù)這個(gè)guide蚯嫌,立馬在parent的pom.xml中增加了這個(gè)配置哲虾,如下圖:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
運(yùn)行命令:
mvn clean package
完美打包成功。查看包的輸出目錄择示,果真有兩個(gè)相似名稱的包束凑,一個(gè)是[name]-[version].jar,另一個(gè)是[name]-[version]-exec.jar对妄。解壓對(duì)比了這兩個(gè)jar,發(fā)現(xiàn)名稱含有-exec為可運(yùn)行包敢朱,而另一個(gè)為普通包(不可通過(guò) java -jar運(yùn)行)剪菱。
自己將classifier配置刪除摩瞎,打包c(diǎn)ommon,查看輸出的jar孝常,發(fā)現(xiàn)是個(gè)可運(yùn)行的包旗们,其它的module無(wú)法依賴可運(yùn)行包。原來(lái)真正的原因在這里构灸!
折磨近一天的問(wèn)題終于解決上渴,潦草記錄該問(wèn)題,可能對(duì)有些人有些幫助喜颁。如果你有任何疑問(wèn)也可以私信來(lái)探討稠氮。
如果你不知道如何利用IntelliJ IDEA創(chuàng)建multi-module的項(xiàng)目,可以參考這篇文章Creating a Multi Module Project