SpringCloud+Maven管理多模塊項目遇到的一些問題以及解決方案


環境

  • SpringCloud Greenwich.SR2
  • Maven3.0.5
  • Idea2019.3

項目結構

Service1 依賴 Common

Service2 依賴 Common

Common 無任何依賴

遇到了什么問題?

mvn package 父項目或 Service 都會報錯,也就是說在 maven 多模塊結構的項目中,引用了一個沒有程序入口的項目將會打包失敗

問題分析 + 解決

下面我對兩種無法通過打包的情況進行分析,並給出解決方案。

Service 項目無法打包

[ERROR] Failed to execute goal on project Service1: Could not resolve dependencies for project org.ccccye:Service:jar:0.0.1-SNAPSHOT: Could not find artifact org.ccccye:common:jar:0.0.1-SNAPSHOT -> [Help 1]

從異常信息中可以知道兩件事

  1. Maven 執行 goal 失敗
  2. goal 執行失敗是因為 Service1 項目所依賴的 common.jar 包找不到

那么問題根源應該是 Service1 項目找不到 common.jar 包造成的。通過翻閱資料和實驗,發現當項目單獨打包時,不會主動去編譯所依賴的模塊項目,而是去本地倉庫找 jar 包,如果用 maven install 把 common.jar 安裝到本地倉庫,是不是能解決問題呢?答案是可以的,在 common 項目執行 mvn install 就可以將 common.jar 安裝到本地倉庫了,,,等等,這里還會出現另外一個問題,接下來繼續講。

父項目無法打包

[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.7.RELEASE:repackage (repackage) on project weather-common: Execution repackage of goal org.springframework.boot:spring-boot-maven-plugin:2.1.7.RELEASE:repackage failed: Unable to find main class -> [Help 1]

從異常信息中可以知道兩件事

  1. 同樣是 Maven 的 goal 執行失敗了,並且明確是 repackge 功能,這說明在將普通 jar 重新打包成可執行 jar 的過程中發生了錯誤
  2. 異常信息中還說了報錯原因是找不到 main 函數造成的

因此問題在 main 函數報錯上,common 項目根本沒有 main 函數並且不需要,這是難為我胖虎啊??翻了資料發現,maven 生成 jar 包的順序是 先生成普通 jar 包,再包裝成可執行 jar(普通 jar 會被覆蓋),注意:可執行程序肯定要有 main 函數的,那么我們可以通過設置 spring-boot-maven-plugin 插件的 layout 參數,賦值為 NONE,maven 只打包所需的依賴,不掃描 main 函數

<plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <layout>NONE</layout>  <!--讓maven不打包可執行jar,不掃描項目的main函數-->
            <classifier>exec</classifier> <!--普通jar和可執行jar不同名,普通jar為xx.jar , 可執行jar為 xx-exec.jar-->
        </configuration>
</plugin>

如上,配置了 layout=NONE 解決了 main 函數問題,在實驗過程中發現,Service1 能正常編譯,一運行就報異常,提示 找不到或無法加載主類 ,原來 Service 想要的 jar 是一個純粹的普通 jar 包,雖然設置了 layout=NONE,但 maven 還是會再打包一次,並且會覆蓋普通的 jar,讓 Service 雖然加載了 jar 包卻找不到 jar 包里面所包含的類,在這里我的解決方案是配置普通 jar 跟二次打包的 jar 不同名,也就是配置

<classifier>exec</classifier>

到此,問題的原因和解決方案都有了,這里總結出來的知識點有

  1. 子項目 package 時的依賴是去本地倉庫或者遠程倉庫查找的,不會主動編譯本地項目並依賴
  2. Maven 默認會執行 repackge 這個 goal
  3. repackge 將普通 jar 改成 xx.jar.original,可執行 jar 為 xx.jar,可以通過 classifier 參數來修改可執行 jar 的名字后綴
  4. 可執行 jar 默認尋找一個 main 函數,通過配置 layout=none 取消

第二種解決方案

還有一種解決方案,在主項目 pom 更換插件,將 spring-boot-maven-plugin 改為 maven-compiler-plugin,具體的配置為

<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
	<source>${java.version}</source>
	<target>${java.version}</target>
</configuration>

然后在主項目運行 package 命令就可以整體編譯打包了。不過要打包 Service 子項目的話,Common 項目得手動 install 安裝到本地倉庫才行。

關聯的知識

  • Maven 的插件模型

總結

主 pom 打包方式 service pom common pom
spring-boot-maven-plugin 整體打包 spring-boot-maven-plugin spring-boot-maven-plugin 增加配置:1. layout=none 2.classifier=exec
部分打包 spring-boot-maven-plugin spring-boot-maven-plugin 增加配置:1. layout=none 2.classifier=exec。打包前需要 install
maven-compiler-plugin 整體打包 spring-boot-maven-plugin 無 build 節點
部分打包 spring-boot-maven-plugin 無 build 節點,打包前需要 install

可以看到部分打包都需要提前 install 公共項目,否則 package 過程中找不到 jar 包;使用 maven-compiler-plugin 不需要增加配置。

值得一說的是這兩個插件並不是同一個類型的,只是剛好能解決問題,它們的區別如下

  • spring-boot-maven-plugin 是打包插件
  • maven-compiler-plugin 是編譯插件

這也就不難理解,為什么 spring-boot-maven-plugin 需要增加配置了,因為它不負責編譯,只能對編譯出來的東西進行打包,因此不能對其他項目進行編譯然后打包到 jar 里;maven-compiler-plugin 可以進行編譯,在編譯階段能將所依賴的其他項目按順序編譯,最后打包進 jar


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM