近期在做一個普通javaweb項目轉轉換成maven項目的任務。
原項目類型:javaWeb項目
兩個源碼包一個產品基礎包,一個基於產品基礎包的開發包,兩個都是普通javaWeb項目。本來應該是開發包可以單邊引用產品基礎包的,由於開發不規范最終導致產品基礎包和開發包存在了相互引用。
針對當時我們的項目我考慮了兩種方案:
方案一、將產品基礎包和開發包整合成一個源碼包,再重構為Maven項目。
產品基礎包編譯成jar包,jsp頁面整合到開發包中。后續產品基礎包如果升級,重新編譯成jar包更換現有jar即可,涉及用到的jsp需要項目組開發團隊整合到正在使用的開發包中按正常版本發布流程提交源碼即可。(這種方案需人工整合為一個源碼包,相互間的引用自然就不存在了)
方案二、使用Maven聚合工程
使用Maven聚合工程,將產品基礎包和開發包分別構建成兩個Maven模塊,然后將開發包目前最新版本打成jar包放入Maven倉庫由產品基礎包引用從而斷掉產品基礎包對開發包之前的引用,之后開發時務必做到開發包單邊引用產品基礎包,便不會再出現產品基礎包對開發包的引用。剩下的就由開發包單邊依賴產品基礎包即可,從而可以避免循環依賴。后續產品基礎包如果升級,按正常版本發布流程提交源碼即可,無需人工整合,各自提交到各自的Maven模塊,無影響。(這種方案后期要確保:開發人員嚴格遵守開發規范開發包單邊引用產品基礎包)
考慮到一下兩種原因,最終采用了第二種方案:
1、整合兩個源碼包需要花費很長時間影響進度,且整合過程中也存在一定的風險。
2、后續產品基礎包可能存在升級
3、還有其他模塊功能待整合上線,需要考慮到可擴展性。
后面再網上查問題時碰到更好的方案,以下內容轉自:https://www.iteye.com/blog/hck-1728329l
很多時候隨着項目的膨脹,模塊會越來越多,如果設計上 稍有不慎就會出現模塊之間相互依賴的情況。這對於使用Maven的用戶是比較痛苦的,因為出現模塊之間相互依賴的話在構建的時候就會失敗,Maven通常要先編譯被依賴的模塊,如果出現相互依賴Maven就不知道該怎么辦了。下圖描述了三個Maven模塊相互依賴的場景:
圖中模塊C依賴於模塊B,模塊B依賴於模塊A,而模塊A又依賴於模塊C,這樣就出現了相互依賴情況,如果運行mvn compile會出現如下錯誤:
[INFO] Scanning for projects... [ERROR] The projects in the reactor contain a cyclic reference: Edge between 'Ve rtex{label='org.kuuyee.sample:module-C:1.0-SNAPSHOT'}' and 'Vertex{label='org.ku uyee.sample:module-B:1.0-SNAPSHOT'}' introduces to cycle in the graph org.kuuyee .sample:module-B:1.0-SNAPSHOT --> org.kuuyee.sample:module-A:1.0-SNAPSHOT --> or g.kuuyee.sample:module-C:1.0-SNAPSHOT --> org.kuuyee.sample:module-B:1.0-SNAPSHO T -> [Help 1][ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e swit ch.[ERROR] Re-run Maven using the -X switch to enable full debug logging.[ERROR] [ERROR] For more information about the errors and possible solutions, please rea d the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectCycleEx ception
1. 使用build-helper-maven-plugin解決相互依賴的問題我的解決辦法就是先把相互依賴的模塊整合在一起,相當於把這些模塊合並成一個單獨的模塊統一編譯,
這樣就產生了一個合並模塊D,我們把它當做一個輔助構建模塊,然后讓A、B、C模塊都依賴於D模塊,這樣的話就可以成功編譯A、B和C模塊,
要想把A、B、C三個模塊整合在一起編譯,需要借助build-helper-maven-plugin插件,這個插件在Maven構建周期提供一些輔助功能,下面列出插件的提供的功能列表: build-helper:add-source:添加更多的構建源碼目錄 build-helper:add-test-source:添加更多的測試源碼目錄 build-helper:add-resource:添加更多的資源目錄 build-helper:add-test-resource:添加更多的測試資源目錄 build-helper:attach-artifact:在安裝和部署周期附加artifacts build-helper:maven-version:添加一個指定當前Maven版本的屬性 build-helper:parse-version:添加一個指定組件版本的屬性 build-helper:released-version:決定當前項目的最終版本 build-helper:remove-project-artifact:從本地資源庫中移除項目的artifacts build-helper:reserve-network-port:Reserve a list of random and unused network ports. 在這里我們要用到build-helper:add-source這個功能,將模塊A、B、C的源碼路徑加進來。 我們再添加一個輔助模塊D,在輔助模塊D中使用build-helper-maven-plugin插件,然后讓模塊A、B、C都依賴於輔助模塊D,模塊D的POM模型如下: 例 1. 輔助模塊D的POM模型
java代碼:
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <groupId>org.kuuyee.sample</groupId>
- <artifactId>sample-parent</artifactId>
- <version>1.0-SNAPSHOT</version>
- <relativePath>../../pom.xml</relativePath>
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.kuuyee.sample</groupId>
- <artifactId>module-D</artifactId>
- <version>1.0-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>module-D</name>
- <url>http://maven.apache.org</url>
- <properties>
- <project.build.sourceEncoding>
- UTF-8
- </project.build.sourceEncoding>
- <module.a.src>../../module/module-A/src/main/java</module.a.src>
- <module.b.src>../../module/module-B/src/main/java</module.b.src>
- <module.c.src>../../module/module-C/src/main/java</module.c.src>
- </properties>
- <build>
- <plugins><!-- 解決模塊相互依賴,綜合所有相互依賴代碼統一編譯 -->
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>add-source</id>
- <phase>generate-sources</phase>
- <goals>
- <goal>add-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>${module.a.src}</source>
- <source>${module.b.src}</source>
- <source>${module.c.src}</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- </project>
maven處理循環依賴
在多maven工程的項目里,如果工程間存在循環依賴,構建就會報錯。本文介紹一下循環依賴要怎么處理
1、什么是循環依賴
如果工程A依賴工程B,工程B又依賴工程A,就會形成循環依賴。或者A依賴B,B依賴C,C依賴A,也是循環依賴
總的來說,在畫出工程依賴圖之后,如果發現工程間的依賴連線形成了一個有向循環圖,則說明有循環依賴的現象
如果循環依賴發生在工程之間,則會影響構建,因為maven不知道應該先編譯哪個工程。如果循環依賴發生在同一個工程的模塊之間,雖然不影響編譯,但是也是一種不好的實踐,說明模塊的設計有問題,應該避免
如果在模塊內部,有幾個類互相調用的話,我覺得可能是正常的。比如觀察者模式里面,Observer和Observable就是互相依賴的
2、怎么解決循環依賴
目前知道有2個辦法可以解決
第一個辦法是用build-helper-maven-plugin插件來規避。比如A依賴B,B依賴C,C依賴A的情況。這個插件提供了一種規避措施,即臨時地將工程A、B、C合並成一個中間工程,編譯出臨時的模塊D。然后A、B、C再分別依賴臨時模塊D進行編譯
這種方法可以解決無法構建的問題,但是只是一個規避措施,工程的依賴關系依然是混亂的
第二個辦法是通過重構,從根本上消除循環依賴
3、如何重構
目前也知道2個重構的思路
第一個辦法是平移,比如A和B互相依賴,那么可以將B依賴A的那部分代碼,移動到工程B中,這樣一來,B就不需要繼續依賴A,只要A依賴B就可以了,從而消除循環依賴
第二個辦法是下移,比如A和B互相依賴,同時它們都依賴C,那么可以將B和A相互依賴的那部分代碼,移動到工程C里,這樣一來,A和B相互之間都不依賴,只繼續依賴C,也可以消除循環依賴
這兩種重構方式都是可行的,具體采用哪種方式要根據實際情況來判斷。不管采取哪種方式,都需要對代碼進行修改,有時候並不是那么容易的