读取jar文件内部的配置信息是在进行开发基于java程序组件时必然会遇到的问题,这里所遇到的问题是在开发测试和部署(也就是将程序打成jar包之后供其他组件调用)时往往会不一致。也就是开发的时候我们的代码可以访问到配置文件信息,但是一旦打成jar包之后往往会遇到“FileNotFoundException”,也就是无法找到配置文件。下面看一个示例。
这是一个测试项目,项目的结构如图所示,现在需要在Main.java类中读取conf.properties文件中的信息。
不一致行为
如果我们在代码中使用下面的语句
- ...
- String confPath = "src/conf/conf.properties";
- FileInputStream fis = new FileInputStream(new File(confPath));
- config.load(fis);
- ...
那么我们打成jar包之前运行程序是可以读取到所要信息,但是打成jar包之后必然会遇到“FileNotFoundException”。而如果使用下面的代码
- ...
- String confPath = "conf/conf.properties";
- FileInputStream fis = new FileInputStream(new File(confPath));
- config.load(fis);
- ...
那么无论是打包之前还是之后都会遇到“FileNotFoundException”的异常!
正确的做法
- ...
- String confPath = "conf/conf.properties";
- config.load(this.getClass().getClassLoader().getResourceAsStream(confPath));
- ...
这时,无论是在打jar包之前还是之后都可以正确读取conf.properties文件中的信息!
原因分析
上面两种截然不同的结果产生的原因是我们使用的FileInputStream和getResourceAsStream()方法的差异所造成的!所以原因也必然在于FileInputStream和getResourceAsStream()的不同。
根据JDK中的表述,FileInputStream是基于当前JVM所在的OS,在文件系统指定的路径中进行查找要求的资源。而ClassLoader类的getResourceAsStream()方面的描述如下:
public InputStream getResourceAsStream(String name)
public URL getResource(String name)
|
Manifest-Version: 1.0
Class-Path: .
Main-Class: com.webex.app.Main
这里的“.”代表当前路径,是一个相对路径,但是它相对的是一个“虚拟路径”,也就是jar或*.class文件加载到JVM后的“路径”!