2021/11/4 更新,可以使用maven-shade-plugin插件解決,更方便並且不用單獨下載jarjar.jar處理。
見這篇博客
先說遇到的問題:
項目本身使用了 Apache poi 3.17 作為excel導出的依賴(既存功能),后來又引入了word生成工具poi-tl 1.10.0版本,使用的poi是4.1.2,導致依賴沖突。
具體體現是編譯無問題,運行時poi-tl出現ClassNotFoundException異常(因為實際使用的是3.17)。
首先想到的是排包,使用高版本依賴,但是經測試發現使用4.1.2時原本的excel功能有問題,使用3.17的時候word功能有問題,即poi 3.17、4.1.2都需要!
解決方案:
使用jarjar對依賴4.1.2的jar包修改包名,同時poi-tl也以相同方式修改包名
首先是jarjar工具的下載,官網的下載地址是這個GoogleCode
再說使用方式:
把下載的jarjar-1.4.jar
包放在英文目錄下,同時把要修改的poi-4.1.2.jar
也放在相同目錄
新建rule.txt,寫上rule org.apache.poi.** com.apache.poi.@1
,這個是改命規則,即把org.apache.poi.**
的全改成com.apache.poi.**
,其中的@1
代表匹配第一個*
或者**
,如果后面還有,就使用@2、@3……
可以先執行命令java -jar jarjar-1.4.jar strings poi-4.1.2.jar
查看是否可以正確讀取包名。
然后執行java -jar jarjar-1.4.jar process rule.txt poi-4.1.2.jar poi-4.1.2-new.jar
,
代表以rule.txt
的規則修改poi-4.1.2.jar
,生成的文件名為poi-4.1.2-new.jar
,新文件名隨意。
如果你按步驟到這里,很可能發現第一條命令執行出現null異常,第二條命令生成的jar包里面並沒有修改成功。
因為官網下載的jarjar.jar不支持修改jdk1.8的jar包!
后來翻官網的issues發現有人提到這個問題
解決方式就是下載jarjar的源碼,替換里面的asm
和asm-common
兩個依賴,我換成了5.0.4,然后修改build.xml
中這兩個版本號,使用ant重新打包
這里放個重新打包好的jarjar包:jarjar-1.4-fixed.jar
后來發現github上的代碼已經更新了依賴,這個是地址
后面的問題就好解決了,使用這個jar包分別對poi-4.1.2.jar
、poi-tl-1.10.0.jar
、poi-ooxml-4.1.2.jar
、poi-ooxml-schemas-4.1.2.jar
執行上面第二個命令,最后把新打的jar包作為第三方依賴添加到項目里面(后面兩個依賴應該不需要修改,但是我實際的操作是一塊改了,沒有實驗不改的情況)
實際最后運行的時候仍然會出現找不到類的情況,不過肯定不是poi里面的類了,這時只需要把缺少的jar包引入進來就行。
順便附一個maven項目中引入第三方依賴的方式,以及讓其打包的配置方式:
首先在src的同級目錄創建一個lib的文件夾,放入jar包然后引用
<dependency>
<!--自定義(隨便填)-->
<groupId>com.apache</groupId>
<!--自定義(隨便填,但需確保不重復)-->
<artifactId>poi</artifactId>
<!--自定義(隨便填)-->
<version>4.1.2</version>
<!--system,類似provided,需要顯式提供依賴的jar以后,Maven就不會在Repository中查找它-->
<scope>system</scope>
<!--項目根目錄下的lib文件夾下-->
<systemPath>${basedir}/lib/poi-4.1.2-new.jar</systemPath>
</dependency>
這種方式需要對打包進行配置:
<build>
<!-- 第三方包打包 -->
<resources>
<resource>
<directory>lib</directory>
<targetPath>/BOOT-INF/lib/</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
</resources>
</build>
另一種方式:
把jar包安裝到本地倉庫:
mvn install:install-file -Dfile=poi-4.1.2-new.jar -DgroupId=com.apache -DartifactId=poi -Dversion=4.1.2 -Dpackaging=jar
然后就可以直接引用:
<dependency>
<groupId>com.apache</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
順便,貼個沒有什么關系的東西:
Maven可以以在groupId
后面加.
的形式引入多個同名不同版本的jar包,參見stackOverflow
參考: