第一眼来看,Maven加载本地Jar包用scope标签下的system不就可以了吗?但这只是踏入坑的开始。
前言
先上案例代码:
Github: liumapp/maven-deal-multy-local-jar
这个项目包含三个模块:
simple-jar-a
simple-jar-b
using-local-jars
simple-jar-a 和 simple-jar-b 是两个简单的程序,用来模拟需要被引入的依赖,及其相关的依赖(即simple-jar下面的依赖)。
using-local-jars加载simple-jar及其附属依赖,并打包发布运行。
所以对于simple-jar不会有过多的叙述,我们的重点在using-local-jars上。
加载本地Jar包
在using-local-jars项目下,我们可以看到一个lib目录,该目录包含了三个jar包,分别是simple-jar-a,simple-jar-b以及它们的依赖commons-io。
那么去看看pom.xml中是如何加载它们这些本地依赖的吧:
<dependencies>
<dependency>
<groupId>org.apache.commons.io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
<scope>system</scope>
<systemPath>${basedir}/lib/commons-io-2.5.jar</systemPath>
</dependency>
<dependency>
<groupId>com.liumapp.simple</groupId>
<artifactId>simple-jar-a</artifactId>
<version>v1.0.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/simple-jar-a-v1.0.0.jar</systemPath>
</dependency>
<dependency>
<groupId>com.liumapp.simple</groupId>
<artifactId>simple-jar-b</artifactId>
<version>v1.0.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/simple-jar-b-v1.0.0.jar</systemPath>
</dependency>
</dependencies>
可以发现,直接使用scope标签的值:system,再指定systemPath及jar包的路径,即可完成加载,通过这个配置,IDEA也能读取本地Jar包,但如果我们使用
mvn clean install
命令,对项目进行打包编译呢?
打包编译
无论我们使用哪一个编译插件:maven-jar-plugin也好、maven-dependency-plugin也罢,或者大名鼎鼎的maven-assembly-plugin也一样,它们的编译过程中,总是会自动的忽略scopr标签,也就是说,我们本地的Jar包,根本不会被编译到最终生成的Jar包内。(虽然我们使用maven-jar-plugin能够把相关依赖的jar包copy到target目录下,但这并不改变无法运行的结果)
配置Meta
但是解决办法总是有的,我们可以通过以下的步骤:
cd target
unzip using-local-jars-v1.0.0.jar -d tmp
进入最终编译的target目录,把最终的jar包解压缩到一个tmp目录下。
cd tmp
vim ./META-INF/MANIFEST.MF
(and add :
Class-Path: lib/commons-io-2.5.jar
lib/simple-jar-a-v1.0.0.jar
lib/simple-jar-b-v1.0.0.jar)
:wq
进入tmp目录后,打开META-INF/MANIFEST.MF配置文件,添加Class-Path属性,并把我们需要的jar包手动加载进去(这里我们把target目录视为根目录)
jar cvfm final.jar ./META-INF/MANIFEST.MF ./
mv final.jar ../
cd ..
java -jar final.jar (if you can find something output , than you are successful .)
最后我们再把修改过的tmp目录下的所有文件打包为一个final.jar,当然,名称您也可以随意定,不过需要指定最终的MANIFEST.MF配置文件,不然,jar cvfm可是会自动生成一个新的不包含Class-Path的配置文件的哦。
最终的测试直接在target目录下运行这个jar包,能够看到相关输出就说明测试成功了。