最近在公司搭建了一套代碼安全質量分析平臺--著名的SonarQube開源版本,再配合jenkins組成自動化流程。
jenkins調用maven做源碼編譯打包,然後調用SonarQube進行代碼掃描,看起來一點問題都沒有。
但是問題來了,公司的項目都是非maven結構的javaweb項目。
上網查了一下,非maven結構的javaweb項目通過更多的定製配置,是完成可以用maven來編譯打包的。
這兩天碰到公司一個javaweb項目,結構比較特殊,項目裏除了引用jar包,還引用了class文件,類似下面的結構
在網上查了半天,找不到這樣項目結構使用maven的相關實踐。運氣比較好的是,之前幫公司配置 pinpoint agent 的時候,恰好了解了一個jvm參數 -classpath,經過在家的一系列實驗,終於把這樣項目結構的工程編譯打包,pom的關鍵配置如下:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<verbose>true</verbose>
<showWarnings>true</showWarnings>
<compilerArgs>
<arg>-extdirs</arg>
<arg>WebContent/WEB-INF/lib</arg>
<arg>-classpath</arg>
<arg>ImportedClasses</arg>
</compilerArgs>
</configuration>
</plugin>
在<compilerArgs>裏設置編譯用的jvm參數,除了常規引用的放在WebContent/WEB-INF/lib裏的所有jar包,還有ImportedClasses目錄下的
所有class文件。
這樣就可以完美的進行編譯和打包了。
回到公司配置好,編譯,報錯。有一個類的一個方法找不到。
這個項目還有一個特別之處,就是其中一個引用的class文件(且稱它爲a.class),跟其中一個jar包裏的class文件的包名、類名一模一樣,反編譯看,兩者內容卻不一樣。
按照上面的配置方法,maven在調用javac編譯源碼,會按順序掃描依賴的文件,直到碰到第一個目標。
看下圖,maven會從這個搜索路徑裏,按順序去找依賴的類,請注意這裏的排序:
- 先是jdk
- 然後到lib裏的jar
- 最後到-classpath 指定的 ImportedClasses
回到那個報錯,因爲源碼裏引用的是 ImportedClasses 裏的 a.class 纔有的方法,而非 jar 裏的a.class,當maven在掃描依賴文件時,首先會碰到 jar 裏的 a.class,然後發現這個類沒有這個方法,於是報錯。
好了,說到這裏,解決思路呼之欲出,就是讓 ImportedClasses 的順序比 lib 靠前。
這個方案網上找了一通,可能是因爲拙略的搜索技巧,找不到別人提供的經驗。
自己各種嘗試,暫時也沒有找到能調整順序的方法。
捨棄javac 的-extdirs參數,全部依賴寫到-classpath裏,就可以自己掌控依賴的搜索順序了。
<compilerArgs>
<arg>-classpath</arg>
<arg>ImportedClasses;WebContent/WEB-INF/lib/fastjson-1.2.47.jar</arg>
</compilerArgs>
把ImportedClasses寫在所有jar之前,編擇成功。
這個方法的缺點就是,當以來的jar包很多的時候,這個值就變得很長,因爲要把每一個jar的路徑寫上去。
碰到這樣的項目結構機率一般比較小,所以這也算是一個maven的冷門使用了。遺憾的是網上似乎找不到關於這種情況的解決方案,特意註冊一個博客,以受批判。