问题描述:
在有几个老项目迁移过来的功能中,有几个比较古董级的jar包比较老,没有maven坐标,然后查阅一些资料,选择引入了本地jar包的配置方式如下:
<dependencies>
<dependency>
<groupId>org.xxx</groupId>
<artifactId>xxx-jar</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/xxx-jar.jar</systemPath>
</dependency>
</dependencies>
此时jar包Maven Dependencies中是存在的,而且运行正常,但是打成jar包放到linux中总是报:
Caused by: java.lang.ClassNotFoundException: org.xhtmlrenderer.pdf.ITextRenderer
但是查看jar包是存在的。
maven版本:apache-maven-3.3.9
问题分析:
由于java.lang.ClassNotFoundExceptionclassLoader未加载到字节码文件导致的,查阅一些关于java中jar包的一些资料了解到在jar的META-INF中有个MANIFEST.MF的配置信息,其中执行maven package的jar包解压后看到
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: liucongcong
Class-Path:
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_91
Main-Class: com.alibaba.dubbo.container.Main
因为java要加载资源是需要有资源基本路径的,不会全局扫描,会在指定好的classpath下进行资源搜索,也就是就算在同一个目录下的,如果classpath没指定到的文件,也是加载不到的。于是解决方案也就有了,那就是将不能加载到的jar配置进去。
问题解决
1、在使用java -classpath lib/*.jar ABC.class 类
这样仅限于启动某个class
2、修改MANIFEST.MF中Class-Path: lib/xx.jar lib/yy.jar
不过这样好像比较麻烦
3、在maven打包插件中配置classpath信息
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<classesDirectory>${project.build.directory}/classes</classesDirectory>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.alibaba.dubbo.container.Main</mainClass>
<useUniqueVersions>false</useUniqueVersions>
</manifest>
<manifestEntries>
<Class-Path>. lib/xx.jar lib/yy.jar</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
总结
1、至于为什么在IDE中启动时为什么没这问题:
在IDE中本身就有配置classpath,而且在IDE中开发maven jar项目时会一般编译到classes中运行,所以在IDE中启动的类会与打成jar后的classpath不太一样。
2、war项目为什么没有这问题:
war包会解压到tomcat中运行,而tomcat本身就有一套classpath管理机制,这就类似这IDE中,只要把jar放到合适的位置,就可以在web项目中使用了。
3、最好还是将这种jar发布到maven私服中引入。